// Enqueue an operation. This is called from a native thread that is not attached to VM. // Also we need to be careful not to execute anything that results in more than a 4k stack. // int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { // listener not running if (!AttachListener::is_initialized()) { return ATTACH_ERROR_DISABLED; } // check that all paramteres to the operation if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(arg1) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(arg2) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG; // check for a well-formed pipename if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG; // grab the lock for the list DWORD res = ::WaitForSingleObject(mutex(), INFINITE); if (res != WAIT_OBJECT_0) { return ATTACH_ERROR_INTERNAL; } // try to get an operation from the available list Win32AttachOperation* op = available(); if (op != NULL) { set_available(op->next()); // add to end (tail) of list op->set_next(NULL); if (tail() == NULL) { set_head(op); } else { tail()->set_next(op); } set_tail(op); op->set_name(cmd); op->set_arg(0, arg0); op->set_arg(1, arg1); op->set_arg(2, arg2); op->set_pipe(pipename); // Increment number of enqueued operations. // Side effect: Semaphore will be signaled and will release // any blocking waiters (i.e. the AttachListener thread). BOOL not_exceeding_semaphore_maximum_count = ::ReleaseSemaphore(enqueued_ops_semaphore(), 1, NULL); guarantee(not_exceeding_semaphore_maximum_count, "invariant"); } ::ReleaseMutex(mutex()); return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE; }
// Enqueue an operation. This is called from a native thread that is not attached to VM. // Also we need to be careful not to execute anything that results in more than a 4k stack. // int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) { // listener not running if (!AttachListener::is_initialized()) { return ATTACH_ERROR_DISABLED; } // check that all paramteres to the operation if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG; // check for a well-formed pipename if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG; // grab the lock for the list DWORD res = ::WaitForSingleObject(mutex(), INFINITE); if (res != WAIT_OBJECT_0) { return ATTACH_ERROR_INTERNAL; } // try to get an operation from the available list Win32AttachOperation* op = available(); if (op != NULL) { set_available(op->next()); // add to end (tail) of list op->set_next(NULL); if (tail() == NULL) { set_head(op); } else { tail()->set_next(op); } set_tail(op); op->set_name(cmd); op->set_arg(0, arg0); op->set_arg(1, arg1); op->set_arg(2, arg2); op->set_pipe(pipename); // wakeup the thread waiting for operations ::ReleaseSemaphore(wakeup(), 1, NULL); } ::ReleaseMutex(mutex()); return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE; }
// Preallocate the maximum number of operations that can be enqueued. int Win32AttachListener::init() { _mutex = (void*)::CreateMutex(NULL, FALSE, NULL); guarantee(_mutex != (HANDLE)NULL, "mutex creation failed"); _enqueued_ops_semaphore = ::CreateSemaphore(NULL, 0, max_enqueued_operations, NULL); guarantee(_enqueued_ops_semaphore != (HANDLE)NULL, "semaphore creation failed"); set_head(NULL); set_tail(NULL); set_available(NULL); for (int i=0; i<max_enqueued_operations; i++) { Win32AttachOperation* op = new Win32AttachOperation(); op->set_next(available()); set_available(op); } return 0; }
// preallocate the required number of operations int Win32AttachListener::init() { _mutex = (void*)::CreateMutex(NULL, FALSE, NULL); guarantee(_mutex != (HANDLE)NULL, "mutex creation failed"); _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL); guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed"); set_head(NULL); set_tail(NULL); // preallocate a few operations set_available(NULL); for (int i=0; i<preallocate_count; i++) { Win32AttachOperation* op = new Win32AttachOperation(); op->set_next(available()); set_available(op); } return 0; }