|
@@ -560,7 +560,6 @@ struct mg_context {
|
|
|
volatile int num_threads; // Number of threads
|
|
|
pthread_mutex_t mutex; // Protects (max|num)_threads
|
|
|
pthread_cond_t cond; // Condvar for tracking workers terminations
|
|
|
- pthread_key_t pthreadTLS; /* Thread local storage index */
|
|
|
|
|
|
struct socket queue[MGSQLEN]; // Accepted sockets
|
|
|
volatile int sq_head; // Head of the socket queue
|
|
@@ -598,6 +597,9 @@ struct mg_connection {
|
|
|
pthread_mutex_t mutex; // Used by mg_lock/mg_unlock to ensure atomic transmissions for websockets
|
|
|
};
|
|
|
|
|
|
+static pthread_key_t sTlsKey; /* Thread local storage index */
|
|
|
+static int sTlsInit = 0;
|
|
|
+
|
|
|
struct mg_workerTLS {
|
|
|
int threadIndex;
|
|
|
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
|
@@ -1114,52 +1116,43 @@ static int pthread_cond_init(pthread_cond_t *cv, const void *unused)
|
|
|
|
|
|
static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
|
|
|
{
|
|
|
+ struct mg_workerTLS * tls = (struct mg_workerTLS *)TlsGetValue(sTlsKey);
|
|
|
+ int ok;
|
|
|
+
|
|
|
EnterCriticalSection(&cv->threadIdSec);
|
|
|
assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
|
|
|
- cv->waitingthreadhdls[cv->waitingthreadcount] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, GetCurrentThreadId());
|
|
|
+ cv->waitingthreadhdls[cv->waitingthreadcount] = tls->pthread_cond_helper_mutex;
|
|
|
cv->waitingthreadcount++;
|
|
|
LeaveCriticalSection(&cv->threadIdSec);
|
|
|
|
|
|
- pthread_mutex_unlock(mutex); /* if the thread is preempted before SuspentThread, ResumeThread will return 0 */
|
|
|
- SuspendThread(GetCurrentThread()); /* if the thread reached this point, ResumeThread will return 1 */
|
|
|
+ pthread_mutex_unlock(mutex);
|
|
|
+ ok = (WAIT_OBJECT_0 == WaitForSingleObject(tls->pthread_cond_helper_mutex, INFINITE));
|
|
|
pthread_mutex_lock(mutex);
|
|
|
|
|
|
- return 0;
|
|
|
+ return ok ? 0 : -1;
|
|
|
}
|
|
|
|
|
|
static int pthread_cond_signal(pthread_cond_t *cv)
|
|
|
{
|
|
|
- int i,j;
|
|
|
- DWORD susCnt;
|
|
|
+ int i;
|
|
|
HANDLE wkup = NULL;
|
|
|
+ BOOL ok = FALSE;
|
|
|
|
|
|
EnterCriticalSection(&cv->threadIdSec);
|
|
|
if (cv->waitingthreadcount) {
|
|
|
- for (;;) {
|
|
|
- for (j=0; j<cv->waitingthreadcount; j++) {
|
|
|
- wkup = cv->waitingthreadhdls[j];
|
|
|
- susCnt = ResumeThread(wkup);
|
|
|
- assert(susCnt<2);
|
|
|
- if (susCnt==1) {
|
|
|
- CloseHandle(wkup);
|
|
|
- for (i=1;i<cv->waitingthreadcount;i++) {
|
|
|
- cv->waitingthreadhdls[i-1] = cv->waitingthreadhdls[i];
|
|
|
- }
|
|
|
- cv->waitingthreadcount--;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (wkup) {
|
|
|
- break;
|
|
|
- } else {
|
|
|
- /* All theads between enqueue and suspend */
|
|
|
- SwitchToThread();
|
|
|
- }
|
|
|
+ wkup = cv->waitingthreadhdls[0];
|
|
|
+ ok = SetEvent(wkup);
|
|
|
+
|
|
|
+ for (i=1;i<cv->waitingthreadcount;i++) {
|
|
|
+ cv->waitingthreadhdls[i-1] = cv->waitingthreadhdls[i];
|
|
|
}
|
|
|
+ cv->waitingthreadcount--;
|
|
|
+
|
|
|
+ assert(ok);
|
|
|
}
|
|
|
LeaveCriticalSection(&cv->threadIdSec);
|
|
|
|
|
|
- return 0;
|
|
|
+ return ok ? 0 : 1;
|
|
|
}
|
|
|
|
|
|
static int pthread_cond_broadcast(pthread_cond_t *cv)
|
|
@@ -5711,9 +5704,9 @@ static void *worker_thread_run(void *thread_func_param)
|
|
|
mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
|
|
|
} else {
|
|
|
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
|
|
- tls->pthread_cond_helper_mutex = CreateMutex(NULL, FALSE, NULL);
|
|
|
+ tls->pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
#endif
|
|
|
- pthread_setspecific(ctx->pthreadTLS, tls);
|
|
|
+ pthread_setspecific(sTlsKey, tls);
|
|
|
conn->buf_size = MAX_REQUEST_SIZE;
|
|
|
conn->buf = (char *) (conn + 1);
|
|
|
conn->ctx = ctx;
|
|
@@ -5756,7 +5749,7 @@ static void *worker_thread_run(void *thread_func_param)
|
|
|
assert(ctx->num_threads >= 0);
|
|
|
(void) pthread_mutex_unlock(&ctx->mutex);
|
|
|
|
|
|
- pthread_setspecific(ctx->pthreadTLS, 0);
|
|
|
+ pthread_setspecific(sTlsKey, 0);
|
|
|
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
|
|
CloseHandle(tls->pthread_cond_helper_mutex);
|
|
|
#endif
|
|
@@ -5996,7 +5989,11 @@ static void free_context(struct mg_context *ctx)
|
|
|
free(ctx->workerthreadids);
|
|
|
}
|
|
|
|
|
|
- pthread_key_delete(ctx->pthreadTLS);
|
|
|
+ /* Deallocate the tls variable */
|
|
|
+ sTlsInit--;
|
|
|
+ if (sTlsInit==0) {
|
|
|
+ pthread_key_delete(sTlsKey);
|
|
|
+ }
|
|
|
|
|
|
// Deallocate context itself
|
|
|
free(ctx);
|
|
@@ -6040,11 +6037,14 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- if (0 != pthread_key_create(&ctx->pthreadTLS, NULL)) {
|
|
|
- mg_cry(fc(ctx), "Cannot initialize thread local storage");
|
|
|
- free(ctx); /* use free only here, and free_context afterwards */
|
|
|
- return NULL;
|
|
|
+ if (sTlsInit==0) {
|
|
|
+ if (0 != pthread_key_create(&sTlsKey, NULL)) {
|
|
|
+ mg_cry(fc(ctx), "Cannot initialize thread local storage");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ sTlsInit++;
|
|
|
}
|
|
|
+
|
|
|
ctx->callbacks = *callbacks;
|
|
|
ctx->user_data = user_data;
|
|
|
ctx->request_handlers = 0;
|