void *read_thread(void *_context) { struct read_args *context = (struct read_args*)_context; int num_threads = context->num_threads; encrypter_context *encrypters = context->encrypters; sender_context *sender_info = context->sender_info; while (true) { for (int i = 0; i < num_threads; i++) { log_print(LOG_DEBUG, "Read: preparing enc: %d \n", i); safe_wait(&sender_info[i].done, &sender_info[i].done_mutex, &sender_info[i].writable); encrypters[i].bytes_read = read(context->fd, encrypters[i].plain, max_block_size); log_print(LOG_DEBUG, "Bytes read: %d\n", encrypters[i].bytes_read); encrypters[i].ready_to_encrypt = true; pthread_cond_signal(&encrypters[i].encrypt_wait); if (encrypters[i].bytes_read <= 0) { *(encrypters[i].readable) = true; pthread_cond_signal(encrypters[i].send_wait); // we are done so lets cleanup for (int j = 0; j < num_threads; j++) { if (j == i) continue; safe_wait(&sender_info[j].done, &sender_info[j].done_mutex, &sender_info[j].writable); log_print(LOG_DEBUG, "cleaning up thread %d becuase thrd %d\n", j, i); encrypters[j].bytes_read = 0; encrypters[j].ready_to_encrypt = true; pthread_cond_signal(&encrypters[j].encrypt_wait); } return NULL; } } } }
void *send_thread(void *_context) { struct send_args *context = (struct send_args*)_context; sender_context *sender_info = context->sender_info; while (true) { for (int i = 0; i < context->num_threads; i++) { int ss; int ssize = 0; safe_wait(&sender_info[i].wait, &sender_info[i].wait_mutex, &sender_info[i].readable); int bytes_read = *sender_info[i].bytes_read; log_print(LOG_DEBUG, "got %d bytes in sender \n", bytes_read); log_print(LOG_DEBUG, "sender enc %s \n", sender_info[i].outdata); if (bytes_read <= 0) return NULL; while (ssize < bytes_read) { if (UDT::ERROR == (ss = UDT::send(*context->udt_socket, sender_info[i].outdata + ssize, bytes_read - ssize, 0))) return NULL; ssize += ss; } sender_info[i].writable = true; pthread_cond_signal(&sender_info[i].done); } } }
void *encrypt_thread(void *_context) { struct encrypter_context* context = (struct encrypter_context*)_context; while (true) { safe_wait(&context->encrypt_wait, &context->mutex, &context->ready_to_encrypt); if (context->bytes_read <= 0) { log_print(LOG_DEBUG, "going to die %d\n", context->plain); return NULL; } log_print(LOG_DEBUG, "encrypter bytes read %d in %d\n", context->bytes_read, context->plain); //context->crypt->encrypt(context->plain, context->encrypted, // context->bytes_read); memcpy(context->encrypted, context->plain, context->bytes_read); log_print(LOG_DEBUG, "enc enc %d %s \n", context->encrypted, context->encrypted); log_print(LOG_DEBUG, "encryption completed in %d for %d\n", context->plain, context->encrypted); *(context->readable) = true; pthread_cond_signal(context->send_wait); } }
/// Blocks to wait for completion of any subprocess. /// /// \return The termination status of the child process that terminated. /// /// \throw process::system_error If the call to wait(2) fails. process::status process::wait_any(void) { const process::status status = safe_wait(); { signals::interrupts_inhibiter inhibiter; signals::remove_pid_to_kill(status.dead_pid()); } return status; }
/// Blocks to wait for completion. /// /// \return The termination status of the child process. /// /// \throw process::system_error If the call to waitpid(2) fails. process::status process::child::wait(void) { const process::status status = safe_wait(_pimpl->_pid); { signals::interrupts_inhibiter inhibiter; signals::remove_pid_to_kill(_pimpl->_pid); } return status; }
OSStatus safe_enter_critical_region(MPCriticalRegionID pCriticalRegionID, Duration lDuration, MPCriticalRegionID pCriticalRegionCriticalRegionID/* = kInvalidID*/) { if(pCriticalRegionCriticalRegionID != kInvalidID) { if(at_mp()) { // enter the critical region's critical region OSStatus lStatus = noErr; AbsoluteTime sExpiration; if(lDuration != kDurationImmediate && lDuration != kDurationForever) { sExpiration = AddDurationToAbsolute(lDuration, UpTime()); } lStatus = MPEnterCriticalRegion(pCriticalRegionCriticalRegionID, lDuration); assert(lStatus == noErr || lStatus == kMPTimeoutErr); if(lStatus == noErr) { // calculate a new duration if(lDuration != kDurationImmediate && lDuration != kDurationForever) { // check if we have any time left AbsoluteTime sUpTime(UpTime()); if(force_cast<uint64_t>(sExpiration) > force_cast<uint64_t>(sUpTime)) { // reset our duration to our remaining time lDuration = AbsoluteDeltaToDuration(sExpiration, sUpTime); } else { // no time left lDuration = kDurationImmediate; } } // if we entered the critical region, exit it again lStatus = MPExitCriticalRegion(pCriticalRegionCriticalRegionID); assert(lStatus == noErr); } else { // otherwise, give up return(lStatus); } } else { // if we're at system task time, try to enter the critical region's critical // region until we succeed. MP tasks will block on this until we let it go. OSStatus lStatus; do { lStatus = MPEnterCriticalRegion(pCriticalRegionCriticalRegionID, kDurationImmediate); } while(lStatus == kMPTimeoutErr); assert(lStatus == noErr); } } // try to enter the critical region function<OSStatus, Duration> oEnterCriticalRegion; oEnterCriticalRegion = bind(MPEnterCriticalRegion, pCriticalRegionID, _1); OSStatus lStatus = safe_wait(oEnterCriticalRegion, lDuration); // if we entered the critical region's critical region to get the critical region, // exit the critical region's critical region. if(pCriticalRegionCriticalRegionID != kInvalidID && at_mp() == false) { lStatus = MPExitCriticalRegion(pCriticalRegionCriticalRegionID); assert(lStatus == noErr); } return(lStatus); }
OSStatus safe_wait_on_semaphore(MPSemaphoreID pSemaphoreID, Duration lDuration) { function<OSStatus, Duration> oWaitOnSemaphore; oWaitOnSemaphore = bind(MPWaitOnSemaphore, pSemaphoreID, _1); return(safe_wait(oWaitOnSemaphore, lDuration)); }
OSStatus safe_wait_on_queue(MPQueueID pQueueID, void **pParam1, void **pParam2, void **pParam3, Duration lDuration) { function<OSStatus, Duration> oWaitOnQueue; oWaitOnQueue = bind(MPWaitOnQueue, pQueueID, pParam1, pParam2, pParam3, _1); return(safe_wait(oWaitOnQueue, lDuration)); }