123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- #ifdef SYSTEM_WIN32
- #pragma warning(push)
- #pragma warning(disable:4100) // unreferenced formal parameter
- #endif
- #ifdef SYSTEM_WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <malloc.h>
- #endif
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include "cmdlib.h"
- #include "messages.h"
- #include "log.h"
- #include "threads.h"
- #include "blockmem.h"
- #ifdef SYSTEM_POSIX
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #ifdef HAVE_SYS_RESOURCE_H
- #include <sys/resource.h>
- #include <pthread.h>
- #endif
- #ifdef HAVE_PTHREAD_H
- #include <pthread.h>
- #endif
- #endif
- #include "hlassert.h"
- q_threadpriority g_threadpriority = DEFAULT_THREAD_PRIORITY;
- #define THREADTIMES_SIZE 100
- #define THREADTIMES_SIZEf (float)(THREADTIMES_SIZE)
- static int dispatch = 0;
- static int workcount = 0;
- static int oldf = 0;
- static bool pacifier = false;
- static bool threaded = false;
- static double threadstart = 0;
- static double threadtimes[THREADTIMES_SIZE];
- int GetThreadWork()
- {
- int r, f, i;
- double ct, finish, finish2, finish3;
- ThreadLock();
- if (dispatch == 0)
- {
- oldf = 0;
- }
- if (dispatch > workcount)
- {
- Developer(DEVELOPER_LEVEL_ERROR, "dispatch > workcount!!!\n");
- ThreadUnlock();
- return -1;
- }
- if (dispatch == workcount)
- {
- Developer(DEVELOPER_LEVEL_MESSAGE, "dispatch == workcount, work is complete\n");
- ThreadUnlock();
- return -1;
- }
- if (dispatch < 0)
- {
- Developer(DEVELOPER_LEVEL_ERROR, "negative dispatch!!!\n");
- ThreadUnlock();
- return -1;
- }
- f = THREADTIMES_SIZE * dispatch / workcount;
- if (pacifier)
- {
- printf("\r%6d /%6d", dispatch, workcount);
- #ifdef ZHLT_PROGRESSFILE // AJM
- if (g_progressfile)
- {
-
- }
- #endif
- if (f != oldf)
- {
- ct = I_FloatTime();
- /* Fill in current time for threadtimes record */
- for (i = oldf; i <= f; i++)
- {
- if (threadtimes[i] < 1)
- {
- threadtimes[i] = ct;
- }
- }
- oldf = f;
- if (f > 10)
- {
- finish = (ct - threadtimes[0]) * (THREADTIMES_SIZEf - f) / f;
- finish2 = 10.0 * (ct - threadtimes[f - 10]) * (THREADTIMES_SIZEf - f) / THREADTIMES_SIZEf;
- finish3 = THREADTIMES_SIZEf * (ct - threadtimes[f - 1]) * (THREADTIMES_SIZEf - f) / THREADTIMES_SIZEf;
- if (finish > 1.0)
- {
- printf(" (%d%%: est. time to completion %ld/%ld/%ld secs) ", f, (long)(finish), (long)(finish2),
- (long)(finish3));
- #ifdef ZHLT_PROGRESSFILE // AJM
- if (g_progressfile)
- {
- }
- #endif
- }
- else
- {
- printf(" (%d%%: est. time to completion <1 sec) ", f);
- #ifdef ZHLT_PROGRESSFILE // AJM
- if (g_progressfile)
- {
- }
- #endif
- }
- }
- }
- }
- else
- {
- if (f != oldf)
- {
- oldf = f;
- switch (f)
- {
- case 10:
- case 20:
- case 30:
- case 40:
- case 50:
- case 60:
- case 70:
- case 80:
- case 90:
- case 100:
- /*
- case 5:
- case 15:
- case 25:
- case 35:
- case 45:
- case 55:
- case 65:
- case 75:
- case 85:
- case 95:
- */
- printf("%d%%...", f);
- default:
- break;
- }
- }
- }
- r = dispatch;
- dispatch++;
- ThreadUnlock();
- return r;
- }
- q_threadfunction workfunction;
- static void ThreadWorkerFunction(int unused)
- {
- int work;
- while ((work = GetThreadWork()) != -1)
- {
- workfunction(work);
- }
- }
- #ifdef SYSTEM_WIN32
- #pragma warning(pop)
- #endif
- void RunThreadsOnIndividual(int workcnt, bool showpacifier, q_threadfunction func)
- {
- workfunction = func;
- RunThreadsOn(workcnt, showpacifier, ThreadWorkerFunction);
- }
- #ifndef SINGLE_THREADED
- /*====================
- | Begin SYSTEM_WIN32
- =*/
- #ifdef SYSTEM_WIN32
- #define USED
- #include <windows.h>
- int g_numthreads = DEFAULT_NUMTHREADS;
- static CRITICAL_SECTION crit;
- static int enter;
- void ThreadSetPriority(q_threadpriority type)
- {
- int val;
- g_threadpriority = type;
- switch (g_threadpriority)
- {
- case eThreadPriorityLow:
- val = IDLE_PRIORITY_CLASS;
- break;
- case eThreadPriorityHigh:
- val = HIGH_PRIORITY_CLASS;
- break;
- case eThreadPriorityNormal:
- default:
- val = NORMAL_PRIORITY_CLASS;
- break;
- }
- SetPriorityClass(GetCurrentProcess(), val);
- }
- #if 0
- static void AdjustPriority(HANDLE hThread)
- {
- int val;
- switch (g_threadpriority)
- {
- case eThreadPriorityLow:
- val = THREAD_PRIORITY_HIGHEST;
- break;
- case eThreadPriorityHigh:
- val = THREAD_PRIORITY_LOWEST;
- break;
- case eThreadPriorityNormal:
- default:
- val = THREAD_PRIORITY_NORMAL;
- break;
- }
- SetThreadPriority(hThread, val);
- }
- #endif
- void ThreadSetDefault()
- {
- SYSTEM_INFO info;
- if (g_numthreads == -1) // not set manually
- {
- GetSystemInfo(&info);
- g_numthreads = info.dwNumberOfProcessors;
- if (g_numthreads < 1 || g_numthreads > 32)
- {
- g_numthreads = 1;
- }
- }
- }
- void ThreadLock()
- {
- if (!threaded)
- {
- return;
- }
- EnterCriticalSection(&crit);
- if (enter)
- {
- Warning("Recursive ThreadLock\n");
- }
- enter++;
- }
- void ThreadUnlock()
- {
- if (!threaded)
- {
- return;
- }
- if (!enter)
- {
- Error("ThreadUnlock without lock\n");
- }
- enter--;
- LeaveCriticalSection(&crit);
- }
- q_threadfunction q_entry;
- static DWORD WINAPI ThreadEntryStub(LPVOID pParam)
- {
- q_entry((int)pParam);
- return 0;
- }
- void threads_InitCrit()
- {
- InitializeCriticalSection(&crit);
- threaded = true;
- }
- void threads_UninitCrit()
- {
- DeleteCriticalSection(&crit);
- }
- void RunThreadsOn(int workcnt, bool showpacifier, q_threadfunction func)
- {
- DWORD threadid[MAX_THREADS];
- HANDLE threadhandle[MAX_THREADS];
- int i;
- double start, end;
- threadstart = I_FloatTime();
- start = threadstart;
- for (i = 0; i < THREADTIMES_SIZE; i++)
- {
- threadtimes[i] = 0;
- }
- dispatch = 0;
- workcount = workcnt;
- oldf = -1;
- pacifier = showpacifier;
- threaded = true;
- q_entry = func;
- if (workcount < dispatch)
- {
- Developer(DEVELOPER_LEVEL_ERROR, "RunThreadsOn: Workcount(%i) < dispatch(%i)\n", workcount, dispatch);
- }
- hlassume(workcount >= dispatch, assume_BadWorkcount);
- //
- // Create all the threads (suspended)
- //
- threads_InitCrit();
- for (i = 0; i < g_numthreads; i++)
- {
- HANDLE hThread = CreateThread(NULL,
- 0,
- (LPTHREAD_START_ROUTINE) ThreadEntryStub,
- (LPVOID) i,
- CREATE_SUSPENDED,
- &threadid[i]);
- if (hThread != NULL)
- {
- threadhandle[i] = hThread;
- }
- else
- {
- LPVOID lpMsgBuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) & lpMsgBuf, 0, NULL);
- // Process any inserts in lpMsgBuf.
- // ...
- // Display the string.
- Developer(DEVELOPER_LEVEL_ERROR, "CreateThread #%d [%08X] failed : %s\n", i, threadhandle[i], lpMsgBuf);
- Fatal(assume_THREAD_ERROR, "Unable to create thread #%d", i);
- // Free the buffer.
- LocalFree(lpMsgBuf);
- }
- }
- CheckFatal();
- // Start all the threads
- for (i = 0; i < g_numthreads; i++)
- {
- if (ResumeThread(threadhandle[i]) == 0xFFFFFFFF)
- {
- LPVOID lpMsgBuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) & lpMsgBuf, 0, NULL);
- // Process any inserts in lpMsgBuf.
- // ...
- // Display the string.
- Developer(DEVELOPER_LEVEL_ERROR, "ResumeThread #%d [%08X] failed : %s\n", i, threadhandle[i], lpMsgBuf);
- Fatal(assume_THREAD_ERROR, "Unable to start thread #%d", i);
- // Free the buffer.
- LocalFree(lpMsgBuf);
- }
- }
- CheckFatal();
- // Wait for threads to complete
- for (i = 0; i < g_numthreads; i++)
- {
- Developer(DEVELOPER_LEVEL_MESSAGE, "WaitForSingleObject on thread #%d [%08X]\n", i, threadhandle[i]);
- WaitForSingleObject(threadhandle[i], INFINITE);
- }
- threads_UninitCrit();
- q_entry = NULL;
- threaded = false;
- end = I_FloatTime();
- if (pacifier)
- {
- printf("\r%60s\r", "");
- }
- Log(" (%.2f seconds)\n", end - start);
- }
- #endif
- /*=
- | End SYSTEM_WIN32
- =====================*/
- /*====================
- | Begin SYSTEM_POSIX
- =*/
- #ifdef SYSTEM_POSIX
- #define USED
- int g_numthreads = DEFAULT_NUMTHREADS;
- void ThreadSetPriority(q_threadpriority type)
- {
- int val;
- g_threadpriority = type;
- // Currently in Linux land users are incapable of raising the priority level of their processes
- // Unless you are root -high is useless . . .
- switch (g_threadpriority)
- {
- case eThreadPriorityLow:
- val = PRIO_MAX;
- break;
- case eThreadPriorityHigh:
- val = PRIO_MIN;
- break;
- case eThreadPriorityNormal:
- default:
- val = 0;
- break;
- }
- setpriority(PRIO_PROCESS, 0, val);
- }
- void ThreadSetDefault()
- {
- if (g_numthreads == -1)
- {
- g_numthreads = 1;
- }
- }
- typedef void* pthread_addr_t;
- pthread_mutex_t* my_mutex;
- void ThreadLock()
- {
- if (my_mutex)
- {
- pthread_mutex_lock(my_mutex);
- }
- }
- void ThreadUnlock()
- {
- if (my_mutex)
- {
- pthread_mutex_unlock(my_mutex);
- }
- }
- q_threadfunction q_entry;
- static void* CDECL ThreadEntryStub(void* pParam)
- {
- q_entry((int)pParam);
- return NULL;
- }
- void threads_InitCrit()
- {
- pthread_mutexattr_t mattrib;
- if (!my_mutex)
- {
- my_mutex = (pthread_mutex_t*)Alloc(sizeof(*my_mutex));
- if (pthread_mutexattr_init(&mattrib) == -1)
- {
- Error("pthread_mutex_attr_init failed");
- }
- if (pthread_mutex_init(my_mutex, &mattrib) == -1)
- {
- Error("pthread_mutex_init failed");
- }
- }
- }
- void threads_UninitCrit()
- {
- Free(my_mutex);
- my_mutex = NULL;
- }
- /*
- * =============
- * RunThreadsOn
- * =============
- */
- void RunThreadsOn(int workcnt, bool showpacifier, q_threadfunction func)
- {
- int i;
- pthread_t work_threads[MAX_THREADS];
- pthread_addr_t status;
- pthread_attr_t attrib;
- double start, end;
- threadstart = I_FloatTime();
- start = threadstart;
- for (i = 0; i < THREADTIMES_SIZE; i++)
- {
- threadtimes[i] = 0;
- }
- dispatch = 0;
- workcount = workcnt;
- oldf = -1;
- pacifier = showpacifier;
- threaded = true;
- q_entry = func;
- if (pacifier)
- {
- setbuf(stdout, NULL);
- }
- threads_InitCrit();
- if (pthread_attr_init(&attrib) == -1)
- {
- Error("pthread_attr_init failed");
- }
- #ifdef _POSIX_THREAD_ATTR_STACKSIZE
- if (pthread_attr_setstacksize(&attrib, 0x400000) == -1)
- {
- Error("pthread_attr_setstacksize failed");
- }
- #endif
- for (i = 0; i < g_numthreads; i++)
- {
- if (pthread_create(&work_threads[i], &attrib, ThreadEntryStub, (void*)i) == -1)
- {
- Error("pthread_create failed");
- }
- }
- for (i = 0; i < g_numthreads; i++)
- {
- if (pthread_join(work_threads[i], &status) == -1)
- {
- Error("pthread_join failed");
- }
- }
- threads_UninitCrit();
- q_entry = NULL;
- threaded = false;
- end = I_FloatTime();
- if (pacifier)
- {
- printf("\r%60s\r", "");
- }
- Log(" (%.2f seconds)\n", end - start);
- }
- #endif /*SYSTEM_POSIX */
- /*=
- | End SYSTEM_POSIX
- =====================*/
- #endif /*SINGLE_THREADED */
- /*====================
- | Begin SINGLE_THREADED
- =*/
- #ifdef SINGLE_THREADED
- int g_numthreads = 1;
- void ThreadSetPriority(q_threadpriority type)
- {
- }
- void threads_InitCrit()
- {
- }
- void threads_UninitCrit()
- {
- }
- void ThreadSetDefault()
- {
- g_numthreads = 1;
- }
- void ThreadLock()
- {
- }
- void ThreadUnlock()
- {
- }
- void RunThreadsOn(int workcnt, bool showpacifier, q_threadfunction func)
- {
- int i;
- double start, end;
- dispatch = 0;
- workcount = workcnt;
- oldf = -1;
- pacifier = showpacifier;
- threadstart = I_FloatTime();
- start = threadstart;
- for (i = 0; i < THREADTIMES_SIZE; i++)
- {
- threadtimes[i] = 0.0;
- }
- if (pacifier)
- {
- setbuf(stdout, NULL);
- }
- func(0);
- end = I_FloatTime();
- if (pacifier)
- {
- printf("\r%60s\r", "");
- }
- Log(" (%.2f seconds)\n", end - start);
- }
- #endif
- /*=
- | End SINGLE_THREADED
- =====================*/
|