void monkey_climb() { sem_acquire(&dominant_monkey); sem_acquire(&tree); printf(1,"monkey %d gets coconut\n", getpid()); sem_signal(&tree); sem_signal(&dominant_monkey); texit(); }
void oReady(void *arg_ptr) { sem_acquire(&h); sem_acquire(&h); sem_signal(&o); sem_signal(&o); lock_acquire(&mutex); water_molecules++; lock_release(&mutex); texit(); }
void qsem_acquire (qsem_t *s) { #ifdef I386 /* no atomic_add() in i386 */ sem_acquire(s->mutex); #else if (atomic_add (&s->count, -1) <= 0) sem_acquire (s->mutex); #endif }
void oReady(void* v) { sem_acquire(&h); sem_acquire(&h); sem_signal(&o); sem_signal(&o); sem_acquire(&l); water++; printf(1,"water molecule created\n"); sem_signal(&l); texit(); }
/* block_cache_sync() - flush all dirty blocks. */ s32 block_cache_sync() { block_descriptor_t *bd, * const end = bc.descriptors + bc.nblocks; u32 one = 1; s32 ret; for(bd = bc.descriptors; bd != end; ++bd) { sem_acquire(&bd->sem); if(bd->flags & BC_DIRTY) { void *data = bc.cache + ((bd - bc.descriptors) * BLOCK_SIZE); ret = bd->dev->write(bd->dev, bd->block, &one, data); if(ret != SUCCESS) return ret; bd->flags &= ~BC_DIRTY; } sem_release(&bd->sem); } return SUCCESS; }
void canarrive(void* daddy) { sem_acquire(&lock); numcan++; if(numcan == 3 || (numcan > 0 && nummiss == 2)){ sem_signal(&can); sem_signal(&can); printf(1, "\nRow Boat"); if (nummiss == 3){ printf(1, " with 3 missionaries"); nummiss = 0; } else if(numcan == 3){ printf(1, " with 3 cannibals"); numcan = 0; } else{ printf(1, " with 1 cannibal 2 missionaries"); numcan = numcan - 1; nummiss = nummiss -2; } } sem_signal(&lock); texit(); }
void consumer(void* arg) { int itm, id; id = *(int *)arg; printf("Consumer %d\n", id); while(1) { sem_acquire(shared.full); sem_acquire(shared.mutex); itm = shared.buf[shared.out]; shared.out = (shared.out + 1) % SH_SIZE; printf("Consumer %d consumed item no %d\n", id, itm); sem_release(shared.mutex); sem_release(shared.empty); sleep(rand() % 3); } }
static void scan_device( ide_bus_info *bus, int device ) { SHOW_FLOW0( 3, "" ); schedule_synced_pc( bus, &bus->scan_bus_syncinfo, (void *)device ); sem_acquire( bus->scan_device_sem, 1 ); }
void test_func2(void *arg) { int* num = (void*)arg; sem_acquire(&s); printf(1,"hey %d.\n",*num); sem_signal(&s); texit(); }
void producer(void* arg) { int id; id = *(int *)arg; printf("Producer %d\n", id); while(1) { sem_acquire(shared.empty); sem_acquire(shared.mutex); shared.buf[shared.in] = item++; shared.in = (shared.in + 1) % SH_SIZE; printf("Producer %d produced item no : %d\n", id, item); sem_release(shared.mutex); sem_release(shared.full); sleep(rand() % 3); } }
void save(struct virtscreen *vscr) { sem_acquire(vscr->lock); if(vscr->data != vscr->back) { memcpy(vscr->back,vscr->data,vscr->num_bytes); vscr->data = vscr->back; } sem_release(vscr->lock); }
void mutex_lock(mutex *m) { thread_id me = thread_get_current_thread_id(); if(me == m->holder) panic("mutex_lock failure: mutex %p acquired twice by thread 0x%x\n", m, me); sem_acquire(m->sem, 1); m->holder = me; }
void vputs(struct virtscreen *vscr, char *s) { sem_acquire(vscr->lock); while(*s) { char_to_virtscreen(vscr, *s); if(*s == '\n') char_to_virtscreen(vscr, '\r'); s++; } sem_release(vscr->lock); }
void task_time() { printf("TIME TASK (ID %d) started.\n",CURRENT_TASK_ID); yield(); while(true) { sem_acquire(&lcd_sem); lcd_cursor(0,0); lcd_printf("Runtime: %d.%d ",millis()/1000, (millis()%1000)/100); sem_release(&lcd_sem); sleep_for(100); } }
void rhine_xmit(rhine *r, const char *ptr, ssize_t len) { #if 0 PANIC_UNIMPLEMENTED(); #if 0 int i; #endif //restart: sem_acquire(r->tx_sem, 1); mutex_lock(&r->lock); #if 0 dprintf("XMIT %d %x (%d)\n",r->txbn, ptr, len); dprintf("dumping packet:"); for(i=0; i<len; i++) { if(i%8 == 0) dprintf("\n"); dprintf("0x%02x ", ptr[i]); } dprintf("\n"); #endif int_disable_interrupts(); acquire_spinlock(&r->reg_spinlock); #if 0 /* wait for clear-to-send */ if(!(RTL_READ_32(r, RT_TXSTATUS0 + r->txbn*4) & RT_TX_HOST_OWNS)) { dprintf("rhine_xmit: no txbuf free\n"); rhine_dumptxstate(r); release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); sem_release(r->tx_sem, 1); goto restart; } #endif memcpy((void*)(r->txbuf + r->txbn * 0x800), ptr, len); if(len < ETHERNET_MIN_SIZE) len = ETHERNET_MIN_SIZE; RTL_WRITE_32(r, RT_TXSTATUS0 + r->txbn*4, len | 0x80000); if(++r->txbn >= 4) r->txbn = 0; release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); #endif }
void keypress(int key) { char c; sem_acquire(active->lock); char_to_virtscreen(active, key); sem_release(active->lock); if(remote_port > 0) { c = key; port_send(send_port, remote_port, &c, 1, 0); } }
void load(struct virtscreen *vscr) { sem_acquire(vscr->lock); if(vscr->data == vscr->back) { vscr->data = screen; memcpy(vscr->data,vscr->back,vscr->num_bytes); } active = vscr; movecursor(vscr->xpos,vscr->ypos); sem_release(vscr->lock); status(vscr - con); }
void reaper(void) { task_t *task; asm("cli"); /* XXX race condition? */ for(;;){ sem_acquire(reaper_sem); task = rsrc_dequeue(reaper_queue); // kprintf("reaper reclaiming thread #%d (%s)",task->rsrc.id,task->rsrc.name); task_destroy(task); } }
void monkey(void* v) { int i = (int)v; while(dominant > 0); sem_acquire(&t); printf(1,"%d\n",i); coconuts++; int j; for(j = 0; j < 100000; j++); printf(1,"%d\n",i); sem_signal(&t); texit(); }
bool recursive_lock_lock(recursive_lock *lock) { thread_id thid = thread_get_current_thread_id(); bool retval = false; if(thid != lock->holder) { sem_acquire(lock->sem, 1); lock->holder = thid; retval = true; } lock->recursion++; return retval; }
void dmonkey(void* v) { int i = (int)v; dominant++; sem_acquire(&t); dominant--; printf(1,"d%d\n",i); coconuts++; int j; for(j = 0; j < 100000; j++); printf(1,"d%d\n",i); sem_signal(&t); texit(); }
int main(int argc, char *argv[]) { //Monkeys climb the tree six times to demonstrate the phenomenom of //dominant monkeys. int n_m=atoi(argv[1]); int d_m=atoi(argv[2]); printf(1,"normal monkeys created: %d\n",n_m); printf(1,"dominant monkeys created: %d\n",d_m); sem_init(&tree,3); if(d_m==0) sem_init(&dominant_monkey,1); else sem_init(&dominant_monkey, d_m); lock_init(&mutex); int j=0; if(argc!=3) { printf(1,"invalid number of arguments\n"); exit(); } void *norm_monkey; int i; for(i=0;i<n_m;i++) { norm_monkey=thread_create(monkey_climb, (void*)&j); if(norm_monkey==0) { printf(1,"thread create fail\n"); exit(); } } void *dom_monkey; for(i=0;i<d_m;i++) { dom_monkey=thread_create(dominant_monkey_climb, (void*)&j); if(dom_monkey==0) { printf(1,"thread create fail\n"); exit(); } //printf(1,"dominant monkey thread created\n"); sem_acquire(&dominant_monkey); } while(wait()>0); printf(1,"Oprah: coconuts for everybody!\n"); exit(); }
static void if_tx_thread(void *args) { ifnet *i = args; cbuf *buf; ssize_t len; t_current_set_name("IF Xmit"); #if IF_PRIO thread_set_priority(i->tx_thread, THREAD_MAX_RT_PRIORITY - 2); #endif //if(i->fd < 0) return -1; //printf("if %x tx thread inited", i); for(;;) { sem_acquire(i->tx_queue_sem); //printf("if %x tx thread gogo\n", i); for(;;) { // pull a packet out of the queue mutex_lock(&i->tx_queue_lock); buf = fixed_queue_dequeue(&i->tx_queue); mutex_unlock(&i->tx_queue_lock); if(!buf) break; #if LOSE_TX_PACKETS if(rand() % 100 < LOSE_TX_PERCENTAGE) { cbuf_free_chain(buf); continue; } #endif // put the cbuf chain into a flat buffer len = cbuf_get_len(buf); cbuf_memcpy_from_chain(i->tx_buf, buf, 0, len); cbuf_free_chain(buf); #if 0||NET_CHATTY dprintf("if_tx_thread: sending packet size %ld\n", (long)len); #endif //sys_write(i->fd, i->tx_buf, 0, len); i->dev->dops.write(i->dev, i->tx_buf, len); } } }
void task_scroller() { printf("SCROLLER TASK (ID %d) started.\n",CURRENT_TASK_ID); yield(); uint8_t mode = 0; while(true) { mode = !mode; for(uint8_t i = 0; i < 16; i++) { sem_acquire(&lcd_sem); lcd_cursor(i,1); lcd_data(mode?0xFF:' '); sem_release(&lcd_sem); sleep_for(20); } } }
// // Test malloc() // int malloc_thread(void*) { for (int i = 0; i < 50000; i++){ #if LOOK_ITS_A_RACE sem_acquire(malloc_sem); #endif free(malloc(10000)); #if LOOK_ITS_A_RACE sem_release(malloc_sem); #endif } printf("malloc thread finished\n"); os_terminate(0); return 0; }
void rtl8169_xmit(rtl8169 *r, const char *ptr, ssize_t len) { int i; #if debug_level_flow >= 3 dprintf("rtl8169_xmit dumping packet:"); hexdump(ptr, len); #endif restart: sem_acquire(r->tx_sem, 1); mutex_lock(&r->lock); int_disable_interrupts(); acquire_spinlock(&r->reg_spinlock); /* look at the descriptor pointed to by tx_idx_free */ if (r->txdesc[r->tx_idx_free].flags & RTL_DESC_OWN) { /* card owns this one, wait and try again later */ release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); // sem_release(r->tx_sem, 1); goto restart; } /* queue it up */ memcpy(TXBUF(r, r->tx_idx_free), ptr, len); if (len < 64) len = 64; r->txdesc[r->tx_idx_free].frame_len = len; r->txdesc[r->tx_idx_free].flags = (r->txdesc[r->tx_idx_free].flags & RTL_DESC_EOR) | RTL_DESC_FS | RTL_DESC_LS | RTL_DESC_OWN; inc_tx_idx_free(r); RTL_WRITE_8(r, REG_TPPOLL, (1<<6)); // something is on the normal queue release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); }
static int if_tx_thread(void *args) { ifnet *i = args; cbuf *buf; ssize_t len; if(i->fd < 0) return -1; for(;;) { sem_acquire(i->tx_queue_sem, 1); for(;;) { // pull a packet out of the queue mutex_lock(&i->tx_queue_lock); buf = fixed_queue_dequeue(&i->tx_queue); mutex_unlock(&i->tx_queue_lock); if(!buf) break; #if LOSE_TX_PACKETS if(rand() % 100 < LOSE_TX_PERCENTAGE) { cbuf_free_chain(buf); continue; } #endif // put the cbuf chain into a flat buffer len = cbuf_get_len(buf); cbuf_memcpy_from_chain(i->tx_buf, buf, 0, len); cbuf_free_chain(buf); #if NET_CHATTY dprintf("if_tx_thread: sending packet size %Ld\n", (long long)len); #endif sys_write(i->fd, i->tx_buf, 0, len); } } }
ssize_t rhine_rx(rhine *r, char *buf, ssize_t buf_len) { PANIC_UNIMPLEMENTED(); #if 0 rx_entry *entry; uint32 tail; uint16 len; int rc; bool release_sem = false; // dprintf("rhine_rx: entry\n"); if(buf_len < 1500) return -1; restart: sem_acquire(r->rx_sem, 1); mutex_lock(&r->lock); int_disable_interrupts(); acquire_spinlock(&r->reg_spinlock); tail = TAILREG_TO_TAIL(RTL_READ_16(r, RT_RXBUFTAIL)); // dprintf("tailreg = 0x%x, actual tail 0x%x\n", RTL_READ_16(r, RT_RXBUFTAIL), tail); if(tail == RTL_READ_16(r, RT_RXBUFHEAD)) { release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); goto restart; } if(RTL_READ_8(r, RT_CHIPCMD) & RT_CMD_RX_BUF_EMPTY) { release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); goto restart; } // grab another buffer entry = (rx_entry *)((uint8 *)r->rxbuf + tail); // dprintf("entry->status = 0x%x\n", entry->status); // dprintf("entry->len = 0x%x\n", entry->len); // see if it's an unfinished buffer if(entry->len == 0xfff0) { release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); goto restart; } // figure the len that we need to copy len = entry->len - 4; // minus the crc // see if we got an error if((entry->status & RT_RX_STATUS_OK) == 0 || len > ETHERNET_MAX_SIZE) { // error, lets reset the card rhine_resetrx(r); release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); goto restart; } // copy the buffer if(len > buf_len) { dprintf("rhine_rx: packet too large for buffer (len %d, buf_len %ld)\n", len, (long)buf_len); RTL_WRITE_16(r, RT_RXBUFTAIL, TAILREG_TO_TAIL(RTL_READ_16(r, RT_RXBUFHEAD))); rc = ERR_TOO_BIG; release_sem = true; goto out; } if(tail + len > 0xffff) { // dprintf("packet wraps around\n"); memcpy(buf, (const void *)&entry->data[0], 0x10000 - (tail + 4)); memcpy((uint8 *)buf + 0x10000 - (tail + 4), (const void *)r->rxbuf, len - (0x10000 - (tail + 4))); } else { memcpy(buf, (const void *)&entry->data[0], len); } rc = len; // calculate the new tail tail = ((tail + entry->len + 4 + 3) & ~3) % 0x10000; // dprintf("new tail at 0x%x, tailreg will say 0x%x\n", tail, TAIL_TO_TAILREG(tail)); RTL_WRITE_16(r, RT_RXBUFTAIL, TAIL_TO_TAILREG(tail)); if(tail != RTL_READ_16(r, RT_RXBUFHEAD)) { // we're at last one more packet behind release_sem = true; } out: release_spinlock(&r->reg_spinlock); int_restore_interrupts(); if(release_sem) sem_release(r->rx_sem, 1); mutex_unlock(&r->lock); #if 0 { int i; dprintf("RX %x (%d)\n", buf, len); dprintf("dumping packet:"); for(i=0; i<len; i++) { if(i%8 == 0) dprintf("\n"); dprintf("0x%02x ", buf[i]); } dprintf("\n"); } #endif return rc; #endif }
/* block_cache_init() - initialise a fixed-size block cache */ s32 block_cache_init(ku32 size) { u32 i; bc.descriptors = (block_descriptor_t *) umalloc(size * sizeof(block_descriptor_t)); if(!bc.descriptors) return ENOMEM; bc.cache = (u8 *) umalloc(size * BLOCK_SIZE); if(!bc.cache) { ufree(bc.descriptors); return ENOMEM; } for(i = 0; i < size; ++i) { bc.descriptors[i] = (block_descriptor_t) { .dev = NULL, .block = 0, .flags = 0 }; sem_init(&bc.descriptors[i].sem); } bc.stats = (block_cache_stats_t) {0}; bc.nblocks = size; printf("block cache: allocated %u bytes (%u blocks)\n", size * BLOCK_SIZE, size); return SUCCESS; } /* block_cache_get_slot() - return the slot in which a cached block must be stored. */ u32 block_cache_get_slot(const dev_t * const dev, ku32 block) { return (((addr_t) dev ^ block) * GREAT_BIG_PRIME) % bc.nblocks; } /* block_read() - read a block, using the block cache. */ s32 block_read(dev_t * const dev, ku32 block, void *buf) { block_descriptor_t *bd; void *data; u32 slot, one = 1; s32 ret; if(dev->type != DEV_TYPE_BLOCK) return EINVAL; if(!bc.nblocks) return dev->read(dev, 0, &one, buf); slot = block_cache_get_slot(dev, block); bd = bc.descriptors + slot; data = bc.cache + (slot * BLOCK_SIZE); sem_acquire(&bd->sem); if((bd->dev != dev) || (bd->block != block)) { if(bd->flags & BC_DIRTY) { /* Descriptor in use; block is dirty; evict it. */ /* FIXME: a failed write here should probably not fail the whole operation */ ret = bd->dev->write(bd->dev, bd->block, &one, data); if(ret != SUCCESS) { sem_release(&bd->sem); return ret; } ++bc.stats.evictions; bd->flags = 0; } /* Read new block into slot */ ret = dev->read(dev, block, &one, data); if(ret != SUCCESS) { sem_release(&bd->sem); return ret; } /* Update descriptor */ bd->dev = dev; bd->block = block; ++bc.stats.misses; } else ++bc.stats.hits; ++bc.stats.reads; memcpy(buf, data, BLOCK_SIZE); sem_release(&bd->sem); return SUCCESS; }
ssize_t rtl8169_rx(rtl8169 *r, char *buf, ssize_t buf_len) { uint32 tail; size_t len; int rc; bool release_sem = false; SHOW_FLOW0(3, "rtl8169_rx: entry\n"); if(buf_len < 1500) return -1; restart: sem_acquire(r->rx_sem, 1); mutex_lock(&r->lock); int_disable_interrupts(); acquire_spinlock(&r->reg_spinlock); /* look at the descriptor pointed to by rx_idx_free */ if (r->rxdesc[r->rx_idx_free].flags & RTL_DESC_OWN) { /* for some reason it's owned by the card, wait for more packets */ release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); goto restart; } /* process this packet */ len = r->rxdesc[r->rx_idx_free].frame_len & 0x3fff; SHOW_FLOW(3, "rtl8169_rx: desc idx %d: len %d\n", r->rx_idx_free, len); if (len > buf_len) { rc = ERR_TOO_BIG; release_sem = true; goto out; } memcpy(buf, RXBUF(r, r->rx_idx_free), len); rc = len; #if debug_level_flow >= 3 hexdump(RXBUF(r, r->rx_idx_free), len); #endif /* stick it back in the free list */ r->rxdesc[r->rx_idx_free].buffer_size = BUFSIZE_PER_FRAME; r->rxdesc[r->rx_idx_free].flags = (r->rxdesc[r->rx_idx_free].flags & RTL_DESC_EOR) | RTL_DESC_OWN; inc_rx_idx_free(r); /* see if there are more packets pending */ if ((r->rxdesc[r->rx_idx_free].flags & RTL_DESC_OWN) == 0) release_sem = true; // if so, release the rx sem so the next reader gets a shot out: release_spinlock(&r->reg_spinlock); int_restore_interrupts(); if(release_sem) sem_release(r->rx_sem, 1); mutex_unlock(&r->lock); return rc; }