1#include "../include/thread.h"
13#include <sys/syscall.h>
19#define MAX_WIN_ERROR 0x7FFFFFFF
26static inline int win_error_to_errno(DWORD win_error) {
28 if (win_error > MAX_WIN_ERROR) {
33 case ERROR_NOT_ENOUGH_MEMORY:
34 case ERROR_OUTOFMEMORY:
36 case ERROR_INVALID_PARAMETER:
37 case ERROR_INVALID_HANDLE:
39 case ERROR_ACCESS_DENIED:
42 return (
int)win_error;
51static inline int is_valid_thread_handle(HANDLE handle) {
return (handle != NULL && handle != INVALID_HANDLE_VALUE); }
70DWORD WINAPI thread_start_wrapper(LPVOID lpParameter) {
71 if (lpParameter == NULL) {
75 ThreadParams* params = (ThreadParams*)lpParameter;
77 void* data = params->data;
82 if (start_routine == NULL) {
83 params->result = NULL;
88 params->result = start_routine(data);
96 if (thread == NULL || start_routine == NULL) {
101 ThreadParams* params = (ThreadParams*)malloc(
sizeof(ThreadParams));
102 if (params == NULL) {
106 params->start_routine = start_routine;
108 params->result = NULL;
111 HANDLE handle = CreateThread(NULL,
113 thread_start_wrapper,
119 if (!is_valid_thread_handle(handle)) {
120 int error = win_error_to_errno(GetLastError());
127 for (
int i = 0; i < 1000 && !params->started; i++) {
135 int ret = pthread_create(thread, NULL, start_routine, data);
141 if (thread == NULL || attr == NULL || start_routine == NULL) {
146 ThreadParams* params = (ThreadParams*)malloc(
sizeof(ThreadParams));
147 if (params == NULL) {
151 params->start_routine = start_routine;
153 params->result = NULL;
156 HANDLE handle = CreateThread(&attr->sa,
158 thread_start_wrapper,
164 if (!is_valid_thread_handle(handle)) {
165 int error = win_error_to_errno(GetLastError());
171 for (
int i = 0; i < 1000 && !params->started; i++) {
179 int ret = pthread_create(thread, attr, start_routine, data);
186 if (!is_valid_thread_handle(tid)) {
190 DWORD wait_result = WaitForSingleObject(tid, INFINITE);
191 if (wait_result != WAIT_OBJECT_0) {
192 return win_error_to_errno(GetLastError());
203 if (retval != NULL) {
205 if (GetExitCodeThread(tid, &exit_code)) {
208 *retval = (
void*)(uintptr_t)exit_code;
219 int ret = pthread_join(tid, retval);
234 ExitThread((DWORD)(uintptr_t)retval);
236 pthread_exit(retval);
242 if (!is_valid_thread_handle(tid)) {
253 if (!CloseHandle(tid)) {
254 return win_error_to_errno(GetLastError());
259 int ret = pthread_detach(tid);
265DWORD
thread_self() {
return GetCurrentThreadId(); }
281 attr->sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
282 attr->sa.lpSecurityDescriptor = NULL;
283 attr->sa.bInheritHandle = FALSE;
287 int ret = pthread_attr_init(attr);
303 int ret = pthread_attr_destroy(attr);
317 if (ms < 0 || (
unsigned int)ms > 0xFFFFFFFE) {
324 ts.tv_sec = ms / 1000;
325 ts.tv_nsec = (ms % 1000) * 1000000L;
328 struct timespec remaining;
329 while (nanosleep(&ts, &remaining) == -1) {
330 if (errno != EINTR) {
340 DWORD pid = GetCurrentProcessId();
347 return (
int)getpid();
353 return (
unsigned long)GetCurrentThreadId();
359 return (
unsigned long)pthread_self();
366 GetSystemInfo(&sysinfo);
367 DWORD count = sysinfo.dwNumberOfProcessors;
370 if (count == 0 || count > LONG_MAX) {
376 long ncpus = sysconf(_SC_NPROCESSORS_ONLN);
393 DWORD current_pid = GetCurrentProcessId();
394 DWORD parent_pid = (DWORD)-1;
396 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
397 if (snapshot == INVALID_HANDLE_VALUE) {
401 pe32.dwSize =
sizeof(PROCESSENTRY32);
402 if (!Process32First(snapshot, &pe32)) {
403 CloseHandle(snapshot);
408 if (pe32.th32ProcessID == current_pid) {
409 parent_pid = pe32.th32ParentProcessID;
412 }
while (Process32Next(snapshot, &pe32));
414 CloseHandle(snapshot);
416 if (parent_pid == (DWORD)-1 || parent_pid > INT_MAX) {
419 return (
int)parent_pid;
429 DWORD token_info_length = 0;
430 TOKEN_USER* token_user = NULL;
431 unsigned int uid_hash = (
unsigned int)-1;
434 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
435 return (
unsigned int)-1;
439 GetTokenInformation(token, TokenUser, NULL, 0, &token_info_length);
440 if (token_info_length == 0) {
442 return (
unsigned int)-1;
445 token_user = (TOKEN_USER*)malloc(token_info_length);
446 if (token_user == NULL) {
448 return (
unsigned int)-1;
452 if (!GetTokenInformation(token, TokenUser, token_user, token_info_length, &token_info_length)) {
455 return (
unsigned int)-1;
459 PSID sid = token_user->User.Sid;
460 if (IsValidSid(sid)) {
461 DWORD sid_length = GetLengthSid(sid);
462 BYTE* sid_bytes = (BYTE*)sid;
465 uid_hash = 2166136261u;
466 for (DWORD i = 0; i < sid_length; i++) {
467 uid_hash ^= sid_bytes[i];
468 uid_hash *= 16777619u;
484 DWORD token_info_length = 0;
485 TOKEN_PRIMARY_GROUP* primary_group = NULL;
486 unsigned int gid_hash = (
unsigned int)-1;
489 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
490 return (
unsigned int)-1;
494 GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &token_info_length);
495 if (token_info_length == 0) {
497 return (
unsigned int)-1;
500 primary_group = (TOKEN_PRIMARY_GROUP*)malloc(token_info_length);
501 if (primary_group == NULL) {
503 return (
unsigned int)-1;
507 if (!GetTokenInformation(token, TokenPrimaryGroup, primary_group, token_info_length, &token_info_length)) {
510 return (
unsigned int)-1;
514 PSID sid = primary_group->PrimaryGroup;
515 if (IsValidSid(sid)) {
516 DWORD sid_length = GetLengthSid(sid);
517 BYTE* sid_bytes = (BYTE*)sid;
520 gid_hash = 2166136261u;
521 for (DWORD i = 0; i < sid_length; i++) {
522 gid_hash ^= sid_bytes[i];
523 gid_hash *= 16777619u;
533static char win_username_buffer[UNLEN + 1];
541 DWORD username_len = UNLEN + 1;
543 if (!GetUserNameA(win_username_buffer, &username_len)) {
547 return win_username_buffer;
551static char win_groupname_buffer[256];
561 DWORD token_info_length = 0;
562 TOKEN_PRIMARY_GROUP* primary_group = NULL;
566 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
571 GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &token_info_length);
572 if (token_info_length == 0) {
577 primary_group = (TOKEN_PRIMARY_GROUP*)malloc(token_info_length);
578 if (primary_group == NULL) {
584 if (!GetTokenInformation(token, TokenPrimaryGroup, primary_group, token_info_length, &token_info_length)) {
591 DWORD name_len =
sizeof(win_groupname_buffer);
592 DWORD domain_len = 0;
593 SID_NAME_USE sid_type;
596 LookupAccountSidA(NULL, primary_group->PrimaryGroup, win_groupname_buffer, &name_len, NULL, &domain_len, &sid_type);
598 if (domain_len > 0) {
599 char* domain_buffer = (
char*)malloc(domain_len);
600 if (domain_buffer != NULL) {
601 name_len =
sizeof(win_groupname_buffer);
602 if (LookupAccountSidA(NULL, primary_group->PrimaryGroup, win_groupname_buffer, &name_len, domain_buffer,
603 &domain_len, &sid_type)) {
604 result = win_groupname_buffer;
618 pid_t ppid = getppid();
620 if (ppid < 0 || ppid > INT_MAX) {
626unsigned int get_uid() {
return (
unsigned int)getuid(); }
628unsigned int get_gid() {
return (
unsigned int)getgid(); }
631 struct passwd* pw = getpwuid(getuid());
640 struct group* gr = getgrgid(getgid());
A modern, cross-platform API for process management and IPC.
void thread_exit(void *retval)
int thread_create(Thread *thread, ThreadStartRoutine start_routine, void *data)
pthread_attr_t ThreadAttr
int thread_attr_destroy(ThreadAttr *attr)
int thread_create_attr(Thread *thread, ThreadAttr *attr, ThreadStartRoutine start_routine, void *data)
int thread_detach(Thread tid)
int thread_join(Thread tid, void **retval)
void *(* ThreadStartRoutine)(void *arg)
int thread_attr_init(ThreadAttr *attr)