/* * thread_DispatchCommand is the thread proc used to dispatch the command to one or more of the qExecs. * * NOTE: This function MUST NOT contain elog or ereport statements. (or most any other backend code) * elog is NOT thread-safe. Developers should instead use something like: * * if (DEBUG3 >= log_min_messages) * write_log("my brilliant log statement here."); * * NOTE: In threads, we cannot use palloc, because it's not thread safe. */ static void * thread_DispatchCommand(void *arg) { DispatchCommandParms *pParms = (DispatchCommandParms *) arg; gp_set_thread_sigmasks(); /* * Mark that we are runnig a new thread. The main thread will check * it to see if there is still alive one. Let's do this after we block * signals so that nobody will intervent and mess up the value. * (should we actually block signals before spawning a thread, as much * like we do in fork??) */ pg_atomic_add_fetch_u32((pg_atomic_uint32 *) &RunningThreadCount, 1); /* * We need to make sure the value will be decremented once the thread * finishes. Currently there is not such case but potentially we could * have pthread_exit or thread cancellation in the middle of code, in * which case we would miss to decrement value if we tried to do this * without the cleanup callback facility. */ pthread_cleanup_push(DecrementRunningCount, NULL); { thread_DispatchOut(pParms); /* * thread_DispatchWaitSingle might have a problem with interupts */ if (pParms->db_count == 1 && false) thread_DispatchWaitSingle(pParms); else thread_DispatchWait(pParms); } pthread_cleanup_pop(1); return (NULL); }
void *cgroupService(void *arg) { int res = FUNC_RETURN_OK; gp_set_thread_sigmasks(); res = CleanUpCGroupAtStartup("cpu"); if (res != FUNC_RETURN_OK) { write_log("%s Function CleanUpCGroupAtStartup failed, " "cgroupService thread will quit", ENFORCER_MESSAGE_HEAD); return NULL; } g_ghash_cgroup = createGHash(GHASH_SLOT_VOLUME_DEFAULT, GHASH_SLOT_VOLUME_DEFAULT_MAX, GHASH_KEYTYPE_SIMPSTR, NULL); if (g_ghash_cgroup == NULL) { write_log("%s Function createGHash failed with out of memory, " "cgroupService thread will quit", ENFORCER_MESSAGE_HEAD); return NULL; } while (true) { /* Timeout in 1 second (1000 ms) */ ResourceEnforcementRequest *task = NULL; task = (ResourceEnforcementRequest *)dequeue(g_queue_cgroup, 1*1000); if (!task) { CleanUpCGroupAtRuntime(); continue; } if (task->type == MOVETO) { res = MoveToCGroup(task->pid, task->cgroup_name); if (res != FUNC_RETURN_OK) { write_log("%s Move PID %d to CGroup %s failed with error %d", ENFORCER_MESSAGE_HEAD, task->pid, task->cgroup_name, res); free(task); break; } } else if (task->type == MOVEOUT) { res = MoveOutCGroup(task->pid, task->cgroup_name); if (res != FUNC_RETURN_OK) { write_log("%s Move PID %d out from CGroup %s failed with error %d", ENFORCER_MESSAGE_HEAD, task->pid, task->cgroup_name, res); free(task); break; } } else if (task->type == SETWEIGHT) { res = SetupWeightCGroup(task->pid, task->cgroup_name, &(task->query_resource)); if (res != FUNC_RETURN_OK) { write_log("%s Set weight %lf for CGroup %s failed with error %d", ENFORCER_MESSAGE_HEAD, task->query_resource.vcore, task->cgroup_name, res); free(task); break; } } else { write_log("%s WARNING :: invalid CGroup task type", ENFORCER_MESSAGE_HEAD); free(task); break; } free(task); CleanUpCGroupAtRuntime(); } write_log("%s Worker thread will quit", ENFORCER_MESSAGE_HEAD); g_enforcement_thread_quited = true; return NULL; }