void * worker_loop(void * arg_void) { WorkerLoopArgs * arg = arg_void; StateMachine * stateMachine; DfaSet * dfaSet = arg->dfaSet; state_machine_id machine_id = arg->machine_id; readlock(dfaSet->lock, machine_id); DEBUG("Worker loop: %ld\n", machine_id); stateMachine = getSmash(dfaSet->smash, machine_id); assert(stateMachine->machine_id == machine_id); if(pthread_detach(stateMachine->worker_thread) != 0) { perror("pthread_detach"); } readunlock(dfaSet->lock); inner_worker_loop(arg_void); writelock(dfaSet->lock, machine_id); DEBUG("Freeing machine %ld\n", machine_id); freeSmash(dfaSet->smash, machine_id); writeunlock(dfaSet->lock); return 0; }
void *reader (void *args) { rwargs *a = static_cast<rwargs *>(args); int d; do { readlock (a->lock, a->id); d = data; usleep (a->delay); readunlock (a->lock); RPMS_DEBUG( LOGNAME, "Reader" + rpms::convert<std::string>(a->id) + ": data = " + rpms::convert<std::string>(d) ); usleep (a->delay); } while (d != 0); RPMS_DEBUG( LOGNAME, "Reader" + rpms::convert<std::string>(a->id) + ": finished" ); return 0; }
void * run_request(DfaSet * dfaSet, state_machine_id machine_id) { void * ret; WorkerLoopArgs * worker_loop_args = malloc(sizeof(WorkerLoopArgs)); StateMachine * machine; readlock(dfaSet->lock, 600); machine = getSmash(dfaSet->smash, machine_id); worker_loop_args->dfaSet = dfaSet; worker_loop_args->machine_id = machine_id; machine->worker_thread = pthread_self(); readunlock(dfaSet->lock); ret = inner_worker_loop(worker_loop_args); return (void*)ret; }
void * inner_worker_loop(void * arg_void) { WorkerLoopArgs * arg = arg_void; DfaSet * dfaSet = arg->dfaSet; const state_machine_id machine_id = arg->machine_id; int timeout = 0; /* Run through the loop immediately the first time around. */ int state = 0; int first = 1; StateMachine* stateMachine; free(arg_void); readlock(dfaSet->lock, machine_id); stateMachine = getSmash(dfaSet->smash, machine_id); pthread_mutex_lock(stateMachine->mutex); while(1) { int rc = 0; state_name i, state_idx = NULL_STATE; /** @todo inner worker loop doesn't seem to 'do the right thing' with respect to timing */ if(1|| !stateMachine->pending) { /* If no pending messages, go to sleep */ struct timeval now; struct timespec timeout_spec; pthread_cond_t * cond; pthread_mutex_t * mutex; long usec; cond = stateMachine->sleepCond; mutex = stateMachine->mutex; readunlock(dfaSet->lock); /* A note on locking: This loop maintains a read lock everywhere except for this call to sleep, and upon termination when it requires a write lock. */ gettimeofday(&now, NULL); usec = now.tv_usec + timeout; if(usec > 1000000) { now.tv_sec++; usec-=1000000; } timeout_spec.tv_sec = now.tv_sec; timeout_spec.tv_nsec = 1000 * usec; rc = pthread_cond_timedwait (cond, mutex, &timeout_spec ); if(rc == EINVAL) { perror("pthread"); } readlock(dfaSet->lock, machine_id); /* Some other thread may have invalidated our pointer while we were sleeping witout a lock... no longer true, *but* since our pointer is local to this thread, we still need to re-read from the store.*/ assert(stateMachine == getSmash(dfaSet->smash, machine_id)); } DEBUG("Current State: %d, %d\n", stateMachine->current_state, NULL_STATE_TOMBSTONE); if(stateMachine->current_state == NULL_STATE_TOMBSTONE) { DEBUG("Freeing statemachine\n"); break; } if(state != stateMachine->current_state) { first = 1; } state = stateMachine->current_state; stateMachine->message.type = stateMachine->current_state; timeout = 690000 +(int) (300000.0*rand()/(RAND_MAX+1.0)); for(i = 0; i < dfaSet->state_count; i++) { if(dfaSet->states[i].name == stateMachine->current_state) { state_idx = i; } } assert(state_idx != NULL_STATE); DEBUG("Worker loop for state machine: %ld still active\n", machine_id); int send = 1; if(dfaSet->states[state_idx].retry_fcn != NULL) { send = dfaSet->states[state_idx].retry_fcn(dfaSet, stateMachine, &(stateMachine->message), stateMachine->message_recipient); } if(send) { if(first) { first = 0; } else { printf("Resending message. Machine # %ld State # %d\n", stateMachine->machine_id, stateMachine->current_state); } send_message(&(dfaSet->networkSetup), &(stateMachine->message), stateMachine->message_recipient); } } setSmash(dfaSet->smash, stateMachine->machine_id); pthread_mutex_unlock(stateMachine->mutex); readunlock(dfaSet->lock); return 0; }