// monitor takes a function pointer (function w/ int as parameter) // and an int to run with the function pointer void enter_monitor(int proc_num, int shm_id, void (*enter_cs)(int)) { time_t tcurrent; struct tm *timeinfo; cond_t *cond; cond = shmat(shm_id,0,0); wait_sem(cond->sem_id,0); // mutex.wait() - wait for free critical section wait_cond(cond); time(&tcurrent); timeinfo = localtime(&tcurrent); fprintf(stderr, "Process %d entering critical section at %d:%02d:%02d\n", proc_num,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); // execute the function sent to the monitor (*enter_cs)(proc_num); time(&tcurrent); timeinfo = localtime(&tcurrent); fprintf(stderr, "Process %d exiting critical section at %d:%02d:%02d\n", proc_num,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); if (cond->next_count > 0) { signal_sem(cond->sem_id,1); // next.signal(); signal_cond(cond); } else { signal_cond(cond); } signal_sem(cond->sem_id,0); // done with critical section shmdt(cond); }
apr_status_t h2_beam_shutdown(h2_bucket_beam *beam, apr_read_type_e block) { apr_status_t status; h2_beam_lock bl; if ((status = enter_yellow(beam, &bl)) == APR_SUCCESS) { r_purge_reds(beam); h2_blist_cleanup(&beam->red); beam_close(beam); report_consumption(beam, 0); while (status == APR_SUCCESS && (!H2_BPROXY_LIST_EMPTY(&beam->proxies) || (beam->green && !APR_BRIGADE_EMPTY(beam->green)))) { if (block == APR_NONBLOCK_READ || !bl.mutex) { status = APR_EAGAIN; break; } if (beam->m_cond) { apr_thread_cond_broadcast(beam->m_cond); } status = wait_cond(beam, bl.mutex); } leave_yellow(beam, &bl); } return status; }
PUBLIC void P(semaphore_t *s) { assert(s); while (!s->count) wait_cond(s->non_empty); s->count--; }
void sema_wait_count(struct sema *sema, int count) { for (;;) { uint32_t oldcount = sema->count; if (oldcount >= count) { if (__sync_bool_compare_and_swap(&sema->count, oldcount, oldcount - count)) return; } else { wait_cond(sema, &sema->count, oldcount); } } }
static apr_status_t r_wait_space(h2_bucket_beam *beam, apr_read_type_e block, h2_beam_lock *pbl, apr_off_t *premain) { *premain = calc_space_left(beam); while (!beam->aborted && *premain <= 0 && (block == APR_BLOCK_READ) && pbl->mutex) { apr_status_t status = wait_cond(beam, pbl->mutex); if (APR_STATUS_IS_TIMEUP(status)) { return status; } r_purge_reds(beam); *premain = calc_space_left(beam); } return beam->aborted? APR_ECONNABORTED : APR_SUCCESS; }
apr_status_t h2_beam_receive(h2_bucket_beam *beam, apr_bucket_brigade *bb, apr_read_type_e block, apr_off_t readbytes) { h2_beam_lock bl; apr_bucket *bred, *bgreen, *ng; int transferred = 0; apr_status_t status = APR_SUCCESS; apr_off_t remain = readbytes; /* Called from the green thread to take buckets from the beam */ if (enter_yellow(beam, &bl) == APR_SUCCESS) { transfer: if (beam->aborted) { if (beam->green && !APR_BRIGADE_EMPTY(beam->green)) { apr_brigade_cleanup(beam->green); } status = APR_ECONNABORTED; goto leave; } /* transfer enough buckets from our green brigade, if we have one */ while (beam->green && !APR_BRIGADE_EMPTY(beam->green) && (readbytes <= 0 || remain >= 0)) { bgreen = APR_BRIGADE_FIRST(beam->green); if (readbytes > 0 && bgreen->length > 0 && remain <= 0) { break; } APR_BUCKET_REMOVE(bgreen); APR_BRIGADE_INSERT_TAIL(bb, bgreen); remain -= bgreen->length; ++transferred; } /* transfer from our red brigade, transforming red buckets to * green ones until we have enough */ while (!H2_BLIST_EMPTY(&beam->red) && (readbytes <= 0 || remain >= 0)) { bred = H2_BLIST_FIRST(&beam->red); bgreen = NULL; if (readbytes > 0 && bred->length > 0 && remain <= 0) { break; } if (APR_BUCKET_IS_METADATA(bred)) { if (APR_BUCKET_IS_EOS(bred)) { bgreen = apr_bucket_eos_create(bb->bucket_alloc); beam->close_sent = 1; } else if (APR_BUCKET_IS_FLUSH(bred)) { bgreen = apr_bucket_flush_create(bb->bucket_alloc); } else { /* put red into hold, no green sent out */ } } else if (APR_BUCKET_IS_FILE(bred)) { /* This is set aside into the target brigade pool so that * any read operation messes with that pool and not * the red one. */ apr_bucket_file *f = (apr_bucket_file *)bred->data; apr_file_t *fd = f->fd; int setaside = (f->readpool != bb->p); if (setaside) { status = apr_file_setaside(&fd, fd, bb->p); if (status != APR_SUCCESS) { goto leave; } ++beam->files_beamed; } ng = apr_brigade_insert_file(bb, fd, bred->start, bred->length, bb->p); #if APR_HAS_MMAP /* disable mmap handling as this leads to segfaults when * the underlying file is changed while memory pointer has * been handed out. See also PR 59348 */ apr_bucket_file_enable_mmap(ng, 0); #endif remain -= bred->length; ++transferred; APR_BUCKET_REMOVE(bred); H2_BLIST_INSERT_TAIL(&beam->hold, bred); ++transferred; continue; } else { /* create a "green" standin bucket. we took care about the * underlying red bucket and its data when we placed it into * the red brigade. * the beam bucket will notify us on destruction that bred is * no longer needed. */ bgreen = h2_beam_bucket_create(beam, bred, bb->bucket_alloc, beam->buckets_sent++); } /* Place the red bucket into our hold, to be destroyed when no * green bucket references it any more. */ APR_BUCKET_REMOVE(bred); H2_BLIST_INSERT_TAIL(&beam->hold, bred); beam->received_bytes += bred->length; if (bgreen) { APR_BRIGADE_INSERT_TAIL(bb, bgreen); remain -= bgreen->length; ++transferred; } } if (readbytes > 0 && remain < 0) { /* too much, put some back */ remain = readbytes; for (bgreen = APR_BRIGADE_FIRST(bb); bgreen != APR_BRIGADE_SENTINEL(bb); bgreen = APR_BUCKET_NEXT(bgreen)) { remain -= bgreen->length; if (remain < 0) { apr_bucket_split(bgreen, bgreen->length+remain); beam->green = apr_brigade_split_ex(bb, APR_BUCKET_NEXT(bgreen), beam->green); break; } } } if (beam->closed && (!beam->green || APR_BRIGADE_EMPTY(beam->green)) && H2_BLIST_EMPTY(&beam->red)) { /* beam is closed and we have nothing more to receive */ if (!beam->close_sent) { apr_bucket *b = apr_bucket_eos_create(bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); beam->close_sent = 1; ++transferred; status = APR_SUCCESS; } } if (transferred) { status = APR_SUCCESS; } else if (beam->closed) { status = APR_EOF; } else if (block == APR_BLOCK_READ && bl.mutex && beam->m_cond) { status = wait_cond(beam, bl.mutex); if (status != APR_SUCCESS) { goto leave; } goto transfer; } else { status = APR_EAGAIN; } leave: leave_yellow(beam, &bl); } return status; }