DECLARE_TEST( mutex, basic ) { mutex_t* mutex; mutex = mutex_allocate( "test" ); EXPECT_STREQ( mutex_name( mutex ), "test" ); EXPECT_TRUE( mutex_try_lock( mutex ) ); EXPECT_TRUE( mutex_lock( mutex ) ); EXPECT_TRUE( mutex_try_lock( mutex ) ); EXPECT_TRUE( mutex_lock( mutex ) ); EXPECT_TRUE( mutex_unlock( mutex ) ); EXPECT_TRUE( mutex_unlock( mutex ) ); EXPECT_TRUE( mutex_unlock( mutex ) ); EXPECT_TRUE( mutex_unlock( mutex ) ); log_set_suppress( 0, ERRORLEVEL_WARNING ); EXPECT_FALSE( mutex_unlock( mutex ) ); log_set_suppress( 0, ERRORLEVEL_INFO ); mutex_signal( mutex ); thread_yield(); EXPECT_TRUE( mutex_wait( mutex, 1 ) ); EXPECT_TRUE( mutex_unlock( mutex ) ); log_set_suppress( 0, ERRORLEVEL_WARNING ); EXPECT_FALSE( mutex_wait( mutex, 100 ) ); EXPECT_FALSE( mutex_unlock( mutex ) ); log_set_suppress( 0, ERRORLEVEL_INFO ); mutex_signal( mutex ); thread_yield(); EXPECT_TRUE( mutex_wait( mutex, 1 ) ); log_set_suppress( 0, ERRORLEVEL_WARNING ); EXPECT_FALSE( mutex_wait( mutex, 100 ) ); EXPECT_TRUE( mutex_unlock( mutex ) ); EXPECT_FALSE( mutex_unlock( mutex ) ); log_set_suppress( 0, ERRORLEVEL_INFO ); mutex_deallocate( mutex ); return 0; }
/* TODO stream is very inefficient of transmiting when receive - * receiver forces transmiter to accasionaly flush out-buffer * */ static unsigned short tcp_stream_getchar (tcp_stream_t *u) { unsigned short c; tcp_socket_t* s = u->socket; if (!s) return -1; mutex_lock (&s->lock); /* Flush output buffer. */ if (u->outptr > u->outdata) { stream_flush (u); mutex_unlock (&s->lock); socket_flush (s); mutex_lock (&s->lock); } if (u->inbuf) mutex_unlock (&s->lock); else { /* Wait for data. */ while (tcp_queue_is_empty (s)) { if (!tcp_socket_is_state(s, TCP_STATES_TRANSFER)) { mutex_unlock (&s->lock); return -1; } mutex_wait (&s->lock); } u->inbuf = tcp_queue_get (s); u->inptr = u->inbuf->payload; mutex_unlock (&s->lock); /*debug_printf ("tstream input"); buf_print (u->inbuf);*/ mutex_lock (&s->ip->lock); if (! (s->flags & TF_ACK_DELAY) && ! (s->flags & TF_ACK_NOW)) { tcp_ack (s); } mutex_unlock (&s->ip->lock); } /* Get byte from buffer. */ c = *u->inptr++; if (u->inptr >= u->inbuf->payload + u->inbuf->len) { buf_t *old = u->inbuf; u->inbuf = old->next; if (u->inbuf) { u->inptr = u->inbuf->payload; old->next = 0; } buf_free (old); } return c; }
/* * Receive interrupt task. */ static void slip_receiver (void *arg) { slip_t *u = arg; unsigned short len; /* Start receiver. */ mutex_lock_irq (&u->netif.lock, RECEIVE_IRQ (u->port), (handler_t) slip_receive_data, u); enable_receiver (u->port); enable_receive_interrupt (u->port); for (;;) { if (! u->in_ptr) { /* Allocate buffer for receive data. */ u->in = buf_alloc (u->pool, u->netif.mtu, 16); if (u->in) { u->in_ptr = u->in->payload; u->in_limit = u->in_ptr + u->netif.mtu; } else { /* No buffer - ignore input. */ debug_printf ("slip_receiver: out of memory\n"); ++u->netif.in_discards; } } /* Wait for the receive interrupt. */ mutex_wait (&u->netif.lock); /* Process all available received data. */ if (u->in_ptr && u->in_ptr > u->in->payload) { len = u->in_ptr - u->in->payload; debug_printf ("slip_receiver(%ld): received %d bytes\n", u->netif.in_packets, len); buf_truncate (u->in, len); ++u->netif.in_packets; if (buf_queue_is_full (&u->inq)) { debug_printf ("slip_receiver: input overflow\n"); ++u->netif.in_discards; /* Reuse the packet. */ u->in_ptr = u->in->payload; u->in_limit = u->in_ptr + u->netif.mtu; } else { /* Enqueue the received packet. */ buf_queue_put (&u->inq, u->in); u->in_ptr = 0; } } #ifndef TRANSMIT_IRQ if (u->out_free) slip_out_next (u); #endif } }
void semaph_wait(semaph_t *sem) { MUTEX_LOCK(&sem->mtx, "semaph"); if (sem->count == 0) { mutex_wait(&sem->mtx); } sem->count--; mutex_unlock(&sem->mtx); }
/* * Wait for transmitter to finish. */ static void uartx_fflush (uartx_t *u) { mutex_lock (&u->transmitter); while (u->out_first != u->out_last) mutex_wait (&u->transmitter); mutex_unlock (&u->transmitter); }
/* * Receive len>0 bytes. Return <0 on error. * When nonblock flag is zero, blocks until data get available (never returns 0). * When nonblock flag is nonzero, returns 0 if no data is available. */ int tcp_read_poll (tcp_socket_t *s, void *arg, unsigned short len, int nonblock) { buf_t *p, *q; char *buf; int n; tcp_debug ("tcp_read(s=%p, arg=%p, len=%u)\n", (void*) s, arg, len); if (len == 0) { return -1; } mutex_lock (&s->lock); while (tcp_queue_is_empty (s)) { if (s->state != SYN_SENT && s->state != SYN_RCVD && s->state != ESTABLISHED) { mutex_unlock (&s->lock); tcp_debug ("tcp_read() called in invalid state\n"); return -1; } if (nonblock) { mutex_unlock (&s->lock); return 0; } mutex_wait (&s->lock); } p = tcp_queue_get (s); tcp_debug ("tcp_read: received %u bytes, wnd %u (%u).\n", p->tot_len, s->rcv_wnd, TCP_WND - s->rcv_wnd); mutex_unlock (&s->lock); mutex_lock (&s->ip->lock); if (! (s->flags & TF_ACK_DELAY) && ! (s->flags & TF_ACK_NOW)) { tcp_ack (s); } mutex_unlock (&s->ip->lock); /* Copy all chunks. */ buf = arg; n = 0; for (q=p; q!=0 && n<len; q=q->next) { int bytes; if (q->len == 0) continue; bytes = (q->len < len-n) ? q->len : len-n; memcpy (buf, q->payload, bytes); n += bytes; buf += bytes; } buf_free (p); return n; }
void* cqueue_extract(cqueue_t *q) { void *p; MUTEX_LOCK(&q->q_mtx, "cqueue"); while ( (p = list_extract_first(&q->q_data)) == NULL ) { mutex_wait(&q->q_mtx); } mutex_unlock(&q->q_mtx); return p; }
/* * Wait for the task to exit, * return the task exit message. */ void * task_wait (task_t *t) { void *message = 0; mutex_lock (&t->finish); while (t->base_prio) message = mutex_wait (&t->finish); mutex_unlock (&t->finish); return message; }
void get_forks (int i, mutex_t *left_fork, mutex_t *right_fork) { for (;;) { mutex_lock (left_fork); if (mutex_trylock (right_fork)) return; mutex_unlock (left_fork); display (i, WAITING); mutex_wait (&table); } }
static void usb_interrupt (void *arg) { static int ep; mutex_lock_irq (io_lock, USB_IRQn, 0, 0); for (;;) { mutex_wait (io_lock); if (ARM_USB->SIS & ARM_USB->SIM & ARM_USB_SC_RESET_EV) { //debug_printf ("usb_interrupt: device reset\n"); ARM_USB->SIS = ARM_USB_SC_RESET_EV; ARM_USB->SIM &= ~ARM_USB_SC_RESET_EV; usbdevhal_reset (usbdev); mldr_usb_reset (); } if (ARM_USB->SIS & ARM_USB->SIM & ARM_USB_SC_SOF_REC) { //debug_printf ("usb_interrupt: start of frame, SIS = %02X, SIM = %02X, SFN = %d.%d\n", ARM_USB->SIS, ARM_USB->SIM, ARM_USB->SFN_L, ARM_USB->SFN_H); ARM_USB->SIS = ARM_USB_SC_SOF_REC; } if (ARM_USB->SIS & ARM_USB->SIM & ARM_USB_SC_TDONE) { ARM_USB->SIS = ARM_USB_SC_TDONE; //debug_printf ("usb_interrupt: tx done, RXFDC = %d, CTRL = %X, STS = %X, TS = %X\n", ARM_USB->SEPF[0].RXFDC_H, ARM_USB->SEPS[0].CTRL, ARM_USB->SEPS[0].STS, ARM_USB->SEPS[0].TS); for (ep = 0; ep < USBDEV_MAX_EP_NB; ++ep) { if (ARM_USB->SEPS[ep].STS & ARM_USB_SC_STALL_SENT) { ARM_USB->SEPS[ep].STS &= ~ARM_USB_SC_STALL_SENT; //debug_printf ("STALL sent\n"); ARM_USB->SEPS[ep].CTRL = (ARM_USB->SEPS[ep].CTRL & ~ARM_USB_EPSSTALL) | ARM_USB_EPRDY; } else if ((ARM_USB->SEPS[ep].CTRL & (ARM_USB_EPEN | ARM_USB_EPRDY)) == ARM_USB_EPEN) { do_usbdev (ep); } } } if (ARM_USB->SIS & ARM_USB->SIM & ARM_USB_SC_RESUME) { //debug_printf ("usb_interrupt: resume\n"); ARM_USB->SIS = ARM_USB_SC_RESUME; } if (ARM_USB->SIS & ARM_USB->SIM & ARM_USB_SC_NAK_SENT) { for (ep = 0; ep < USBDEV_MAX_EP_NB; ++ep) { if ((ARM_USB->SEPS[ep].CTRL & (ARM_USB_EPEN | ARM_USB_EPRDY)) == ARM_USB_EPEN) { //debug_printf ("NAK sent, EP%d CTRL = %x, STS = %x\n", ep, ARM_USB->SEPS[ep].CTRL, ARM_USB->SEPS[ep].STS); if (ARM_USB->SEPS[ep].STS & ARM_USB_SC_ACK_RXED || ARM_USB->SEPS[ep].STS == 0x90) do_usbdev (ep); if (ARM_USB->SEPS[ep].CTRL & ARM_USB_EPSSTALL) //ARM_USB->SEPS[ep].CTRL |= ARM_USB_EPRDY; ARM_USB->SEPS[ep].CTRL = (ARM_USB->SEPS[ep].CTRL & ~ARM_USB_EPSSTALL) | ARM_USB_EPRDY; } } ARM_USB->SIS = ARM_USB_SC_NAK_SENT; } } }
int mutex_lock(struct mutex_t *mutex) { DEBUG("%s: trying to get mutex. val: %u\n", active_thread->name, mutex->val); if (atomic_set_return(&mutex->val, 1) != 0) { /* mutex was locked. */ mutex_wait(mutex); } return 1; }
int cb_rem_blocking(CircBuff_t * cb, float * in, const size_t len) { if (cb->invalid) return CB_ERROR; if (len <= 0) return CB_OK; size_t items_inside = cb->buffer_size - cb->remaining_capacity; while (items_inside < len) { // if the size of the buffer is not large enough, request a resize during the next add if (len*cb->size_coeff > cb->buffer_size) cb->desired_buf_size = len*cb->size_coeff; const size_t before_items_inside = items_inside; cb->is_waiting = 1; if (mutex_wait(&cb->locker) == THREAD_TIMEOUT) { cb->is_waiting = 0; return CB_EMPTY; } cb->is_waiting = 0; items_inside = cb->buffer_size - cb->remaining_capacity; if (before_items_inside == items_inside) return CB_EMPTY; // if there are not enough items } if (cb->invalid) return CB_ERROR; critical_enter(&cb->mutex); #if ASSERT_ENABLED assert(((cb->pos + cb->remaining_capacity) % cb->buffer_size) == cb->rempos); #endif if (cb->buffer_size - cb->remaining_capacity < len) { critical_leave(&cb->mutex); return CB_EMPTY; } const size_t oldrempos = cb->rempos; cb->rempos = (oldrempos + len) % cb->buffer_size; // calculate new position if (cb->rempos <= oldrempos) { // we have to wrap around const size_t remaining = cb->buffer_size - oldrempos; memcpy(in, (void *) &cb->buffer[oldrempos], remaining*sizeof(float)); memcpy(&in[remaining], (void *) cb->buffer, cb->rempos*sizeof(float)); } else { // we don't have to wrap around memcpy(in, (void *) &cb->buffer[oldrempos], len*sizeof(float)); } cb->remaining_capacity += len; // we have removed len items critical_leave(&cb->mutex); return CB_OK; }
void task_test(void* arg) { debug_printf("test task init\n"); mutex_lock(&lock); while (1) { mutex_wait(&lock); debug_printf("test irq %d\n", counter); } }
/* * Connect to another host. Wait until connection established. * Return 1 on success, 0 on error. */ tcp_socket_t * tcp_connect (ip_t *ip, unsigned char *ipaddr, unsigned short port) { tcp_socket_t *s; unsigned long optdata; tcp_debug ("tcp_connect to port %u\n", port); if (ipaddr == 0) return 0; mutex_lock (&ip->lock); s = tcp_alloc (ip); memcpy (s->remote_ip, ipaddr, 4); s->remote_port = port; if (s->local_port == 0) { s->local_port = tcp_new_port (ip); } s->lastack = s->snd_nxt - 1; s->snd_lbb = s->snd_nxt - 1; s->snd_wnd = TCP_WND; s->ssthresh = s->mss * 10; s->state = SYN_SENT; /* Build an MSS option */ optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) | (((unsigned long)s->mss / 256) << 8) | (s->mss & 255)); if (! tcp_enqueue (s, 0, 0, TCP_SYN, (unsigned char*) &optdata, 4)) { mem_free (s); mutex_unlock (&ip->lock); return 0; } tcp_list_add (&ip->tcp_sockets, s); tcp_output (s); mutex_unlock (&ip->lock); mutex_lock (&s->lock); for (;;) { mutex_wait (&s->lock); if (s->state == ESTABLISHED) { mutex_unlock (&s->lock); return s; } if (s->state == CLOSED) { mutex_unlock (&s->lock); mem_free (s); return 0; } } }
void hello (void *arg) { for (;;) { //debug_printf ("STATUS = %08x\n", mips_read_c0_register (C0_STATUS)); //debug_printf ("CAUSE = %08x\n", mips_read_c0_register (C0_CAUSE)); //debug_printf ("INTCTL = %08x\n", mips_read_c0_select (C0_INTCTL, 1)); //debug_printf ("EBASE = %08x\n", mips_read_c0_select (C0_EBASE, 1)); //debug_printf ("INTCON = %08x\n", INTCON); debug_printf ("Hello from `%s'! msec = %d\n", arg, timer_milliseconds (&timer)); mutex_wait (&timer.decisec); } }
/* * Interrupt task. */ static void interrupt_task(void *arg) { eth_t *u = arg; /* Register the interrupt. */ mutex_lock_irq(&u->netif.lock, ETH_IRQ, 0, 0); for (;;) { /* Wait for the interrupt. */ mutex_wait(&u->netif.lock); ++u->intr; handle_interrupt(u); } }
/* * Задача выдачи статистики на консоль. */ void console (void *arg) { for (;;) { mutex_wait (&timer_lock); debug_puts ("\33[H"); debug_puts ("Measuring interrupt latency.\n\n"); debug_printf ("CPU frequency: %u MHz\n", KHZ / 1000); debug_printf ("\n"); debug_printf (" Interrupts: %u \n\n", nirqs); print_rational (" Latency, min: ", latency_min * 1000, KHZ); print_rational (" max: ", latency_max * 1000, KHZ); } }
/* * Get the received packet. Blocks the task until the data is available. */ buf_t * slip_recv (slip_t *u) { buf_t *p; mutex_lock (&u->netif.lock); for (;;) { p = buf_queue_get (&u->inq); if (p) { mutex_unlock (&u->netif.lock); return p; } mutex_wait (&u->netif.lock); } }
static void interface_add (ipv4_interface_type *interface, ipc_structure_type *ethernet_structure) { ipv4_interface_list_type *entry; memory_allocate ((void **) &entry, sizeof (ipv4_interface_list_type)); entry->interface = interface; entry->ethernet_structure = ethernet_structure; /* Add this entry into the list. */ mutex_wait (interface_list_mutex); entry->next = (struct ipv4_interface_list_type *) interface_list; interface_list = entry; mutex_signal (interface_list_mutex); }
/* * Transmit interrupt task. */ static void slip_transmitter (void *arg) { slip_t *u = arg; /* Start transmitter. */ mutex_lock_irq (&u->transmitter, TRANSMIT_IRQ (u->port), (handler_t) slip_transmit_start, u); enable_transmitter (u->port); for (;;) { /* Wait for the transmit interrupt. */ mutex_wait (&u->transmitter); if (u->out_free) slip_out_next (u); } }
/* * Wait for the byte to be received and return it. */ static unsigned short uartx_getchar (uartx_t *u) { unsigned char c; mutex_lock (&u->receiver); /* Wait until receive data available. */ while (u->in_first == u->in_last) mutex_wait (&u->receiver); /* TODO: utf8 to unicode conversion. */ c = *u->in_first++; if (u->in_first >= u->in_buf + UART_INBUFSZ) u->in_first = u->in_buf; mutex_unlock (&u->receiver); return c; }
static unsigned int interface_get_amount (void) { ipv4_interface_list_type *entry; unsigned int counter = 0; mutex_wait (interface_list_mutex); entry = interface_list; while (entry != NULL) { counter++; entry = (ipv4_interface_list_type *) entry->next; } mutex_signal (interface_list_mutex); return counter; }
void hello (void *data) { buf_t *p; debug_printf ("\n*** Testing SLIP on UART 1 ***\n"); mutex_lock (&slip.netif.lock); for (;;) { mutex_wait (&slip.netif.lock); p = netif_input (&slip.netif); if (p) { buf_print_ip (p); #if 1 netif_output (&slip.netif, p, 0, 0); #else buf_free (p); #endif } } }
/* * Задача приёма сообщений. */ void receiver (void *arg) { unsigned t0, t1, latency; for (;;) { t0 = (unsigned) mutex_wait (&mailbox); t1 = mips_read_c0_register (C0_COUNT); /* Вычисляем количество тактов, затраченных на вход в прерывание. */ latency = t1 - t0; /*debug_printf ("<%u> ", latency);*/ if (++nmessages > 10) { if (latency_min > latency) latency_min = latency; if (latency_max < latency) latency_max = latency; } } }
/* * Send a byte to the UART transmitter. */ static void uartx_putchar (uartx_t *u, short c) { unsigned char *newlast; mutex_lock (&u->transmitter); newlast = u->out_last + 1; if (newlast >= u->out_buf + UART_OUTBUFSZ) newlast = u->out_buf; while (u->out_first == newlast) mutex_wait (&u->transmitter); /* TODO: unicode to utf8 conversion. */ *u->out_last = c; u->out_last = newlast; uartx_transmit_start (u); mutex_unlock (&u->transmitter); }
/* * Задача приёма сообщений. */ void receiver (void *arg) { unsigned t0, t1, latency; for (;;) { t0 = (unsigned) mutex_wait (&mailbox); t1 = ARM_SYSTICK->VAL; /* Вычисляем количество тактов, затраченных на вход в прерывание. */ latency = t0 - t1; /*debug_printf ("<%u> ", latency);*/ if (++nmessages > 10) { if (latency_min > latency) latency_min = latency; if (latency_max < latency) latency_max = latency; } } }
static void* thread_wait( object_t thread, void* arg ) { mutex_t* mutex = arg; FOUNDATION_UNUSED( thread ); FOUNDATION_UNUSED( arg ); atomic_incr32( &thread_waiting ); if( mutex_wait( mutex, 30000 ) ) { atomic_incr32( &thread_waited ); mutex_unlock( mutex ); } else { log_warn( HASH_TEST, WARNING_SUSPICIOUS, "Thread timeout" ); } return 0; }
DECLARE_TEST( mutex, signal ) { mutex_t* mutex; object_t thread[32]; int ith; mutex = mutex_allocate( "test" ); mutex_lock( mutex ); for( ith = 0; ith < 32; ++ith ) { thread[ith] = thread_create( thread_wait, "thread_wait", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[ith], mutex ); } mutex_unlock( mutex ); test_wait_for_threads_startup( thread, 32 ); while( atomic_load32( &thread_waiting ) < 32 ) thread_yield(); thread_sleep( 1000 ); //Hack wait to give threads time to progress from atomic_incr to mutex_wait mutex_signal( mutex ); for( ith = 0; ith < 32; ++ith ) { thread_terminate( thread[ith] ); thread_destroy( thread[ith] ); } test_wait_for_threads_exit( thread, 32 ); EXPECT_EQ( atomic_load32( &thread_waited ), 32 ); EXPECT_FALSE( mutex_wait( mutex, 500 ) ); mutex_deallocate( mutex ); return 0; }
/* * Send the packet. Blocks the task until the packet is enqueued. */ bool_t slip_send (slip_t *u, buf_t *p) { mutex_lock (&u->transmitter); while (u->out && buf_queue_is_full (&u->outq)) mutex_wait (&u->transmitter); if (u->out) { /* Занято, ставим в очередь. */ buf_queue_put (&u->outq, p); } else { u->out = p; u->outseg = p; u->out_first = u->outseg->payload; u->out_limit = u->outseg->payload + u->outseg->len; u->out_flag = 1; slip_transmit_start (u); } mutex_unlock (&u->transmitter); return 1; }
/* * Connect to another host. Wait until connection established. * Return 1 on success, 0 on error. */ tcp_socket_t * tcp_connect (ip_t *ip, unsigned char *ipaddr, unsigned short port) { tcp_socket_t* s = tcp_connect_start(ip, ipadr_4ucs(ipaddr), port); if ((s == 0) || SEANYERROR(s)) return s; mutex_lock (&s->lock); for (;;) { if (s->state == ESTABLISHED) { mutex_unlock (&s->lock); return s; } if (s->state == CLOSED) { mutex_unlock (&s->lock); mem_free (s); return 0; } mutex_wait (&s->lock); } }