int main_the_rest (void) { while (1) { main_thread_ready = 1; semaphore_enter (background_sem); if (db_shutdown) { sf_shutdown (NULL, NULL); } else { if (main_continuation_reason == MAIN_CONTINUE_ON_SCHEDULER && cfg_scheduler_period > 0) { sched_do_round (); } else if (cfg_autocheckpoint) { sf_make_auto_cp (); /* Use the one and same old log file. */ } else /* Should not happen! */ { GPF_T1 ("Initial thread continued, " "although autocheckpointing is not used."); } main_continuation_reason = MAIN_CONTINUE_ON_CHECKPOINT; } } return 0; }
static void *high_run(void *arg) { test_emit('e'); semaphore_enter(&s); test_emit('g'); semaphore_leave(&s); test_emit('h'); return NULL; }
static void *mid_run(void *arg) { test_emit('c'); semaphore_enter(&s); test_emit('d'); test_assert_zero(thread_launch(high)); test_emit('f'); semaphore_leave(&s); test_emit('i'); return NULL; }
static void *low_run(void *arg) { test_emit('a'); semaphore_enter(&s); test_emit('b'); test_assert_zero(thread_launch(mid)); test_emit('j'); semaphore_leave(&s); test_emit('k'); return NULL; }
int mutex_enter (dk_mutex_t *mtx) #endif { #ifndef MTX_DEBUG return semaphore_enter (mtx->mtx_handle); #else semaphore_t *sem = (semaphore_t *) mtx->mtx_handle; #ifdef MALLOC_DEBUG if (_current_fiber == NULL) { assert (mtx == _dbgmal_mtx); return semaphore_enter (sem); } #endif assert (_current_fiber != NULL); if (sem->sem_entry_count) { assert (sem->sem_entry_count == 1); assert (mtx->mtx_owner == NULL); sem->sem_entry_count--; } else { assert (mtx->mtx_owner != _current_fiber); thread_queue_to (&sem->sem_waiting, _current_fiber); _fiber_status (_current_fiber, WAITSEM); _fiber_schedule_next (); assert (sem->sem_entry_count == 0); } assert (mtx->mtx_owner == NULL); if (mtx->mtx_entry_check && !mtx->mtx_entry_check (mtx, THREAD_CURRENT_THREAD, mtx->mtx_entry_check_cd)) GPF_T1 ("Mtx entry check fail"); mtx->mtx_owner = _current_fiber; mtx->mtx_entry_file = (char *) file; mtx->mtx_entry_line = line; return 0; #endif }
static void freeze_thread_write (dk_session_t * ses) { USE_GLOBAL SESSION_SCH_DATA (ses)->sio_random_write_ready_action = unfreeze_thread_write; SESSION_SCH_DATA (ses)->sio_writing_thread = current_process; add_to_served_sessions (ses); ss_dprintf_4 (("Write on Thread %p blocked.", (void *) current_process)); semaphore_enter (current_process->thr_sem); }
/* service_read () Used to read from a session. Handles scheduling if the session would block. Used for reading from a service thread. If the read would block, put the thread to wait. When the scheduling cycle sees input on this session the random_input_ready_action is called. This wakes up this thread and schedules it for execution on the next round The need_all argument controls whether this function may return after reading fewer than the requested number of bytes. This function always reads at least 1 byte. If the calling thread is the scheduling thread and io would block, this allows schedule and recursively blocks on all pending i/o. If the calling thread is some other thread, this disables the thread and tells the scheduler to resume this when the input is ready. Returns the number of bytes read. */ int service_read (dk_session_t * ses, char *buffer, int req_bytes, int need_all) { USE_GLOBAL int last_read = 0; int bytes = req_bytes; du_thread_t *cur_proc; /* mty NEW */ int rc; DBG_CHECK_READ_FAIL (ses); while (bytes > 0) { without_scheduling_tic (); if (!ses->dks_is_read_select_ready && ses->dks_session && ses->dks_session->ses_class != SESCLASS_STRING) { tcpses_is_read_ready (ses->dks_session, &ses->dks_read_block_timeout); if (DKSESSTAT_ISSET (ses, SST_TIMED_OUT)) rc = -1; else rc = session_read (ses->dks_session, &(buffer[last_read]), bytes); } else { if (!ses->dks_session) longjmp_splice (&(SESSION_SCH_DATA (ses)->sio_read_broken_context), 1); rc = session_read (ses->dks_session, &(buffer[last_read]), bytes); } ses->dks_is_read_select_ready = 0; restore_scheduling_tic (); if (rc == 0) PROCESS_ALLOW_SCHEDULE (); else if (rc > 0) { bytes = bytes - rc; last_read = last_read + rc; if (!need_all) { ses->dks_bytes_received += last_read; return (last_read); } } if (rc <= 0) { if (SESSTAT_ISSET (ses->dks_session, SST_INTERRUPTED)) { PROCESS_ALLOW_SCHEDULE (); } else if (SESSTAT_ISSET (ses->dks_session, SST_BLOCK_ON_READ)) { /* would block. suspend thread */ cur_proc = current_process; /* mty NEW */ if (!PROCESS_TO_DK_THREAD (cur_proc)) { /* We have a block on a server thread. We recognize it * because a server thread is not associated to a request. * The read would block the server thread. Run others and * do a recursive check_inputs to resume other threads that * may now be ready for i/o. Do a timeout round to unblock * threads waiting on timed-out futures if the select times * out. Finally retry read. */ int rc2; PROCESS_ALLOW_SCHEDULE (); rc2 = check_inputs (PASS_G & atomic_timeout, 1); if (rc2 == 0) timeout_round (PASS_G ses); } else { SESSION_SCH_DATA (ses)->sio_random_read_ready_action = unfreeze_thread_read; SESSION_SCH_DATA (ses)->sio_reading_thread = cur_proc; add_to_served_sessions (ses); semaphore_enter (cur_proc->thr_sem); } } else if (1 || /* ?? */ SESSTAT_ISSET (ses->dks_session, SST_TIMED_OUT) || SESSTAT_ISSET (ses->dks_session, SST_BROKEN_CONNECTION)) { SESSTAT_CLR (ses->dks_session, SST_OK); SESSTAT_SET (ses->dks_session, SST_BROKEN_CONNECTION); longjmp_splice (&(SESSION_SCH_DATA (ses)->sio_read_broken_context), 1); } else { ses->dks_bytes_received += last_read; ss_dprintf_2 (("Unrecognized I/O error rc=%d errno=%d in service_read.", rc, errno)); longjmp_splice (&(SESSION_SCH_DATA (ses)->sio_read_broken_context), 1); } } } ses->dks_bytes_received += last_read; return (last_read); }