js/src/vm/PosixNSPR.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "vm/PosixNSPR.h"
     9 #include "js/Utility.h"
    11 #ifdef JS_POSIX_NSPR
    13 #include <errno.h>
    14 #include <sys/time.h>
    15 #include <time.h>
    17 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
    18 #include <pthread_np.h>
    19 #endif
    21 class nspr::Thread
    22 {
    23     pthread_t pthread_;
    24     void (*start)(void *arg);
    25     void *arg;
    26     bool joinable;
    28   public:
    29     Thread(void (*start)(void *arg), void *arg, bool joinable)
    30       : start(start), arg(arg), joinable(joinable) {}
    32     static void *ThreadRoutine(void *arg);
    34     pthread_t &pthread() { return pthread_; }
    35 };
    37 static pthread_key_t gSelfThreadIndex;
    38 static nspr::Thread gMainThread(nullptr, nullptr, false);
    40 void *
    41 nspr::Thread::ThreadRoutine(void *arg)
    42 {
    43     Thread *self = static_cast<Thread *>(arg);
    44     pthread_setspecific(gSelfThreadIndex, self);
    45     self->start(self->arg);
    46     if (!self->joinable)
    47         js_delete(self);
    48     return nullptr;
    49 }
    51 static bool gInitialized;
    53 void
    54 DummyDestructor(void *)
    55 {
    56 }
    58 /* Should be called from the main thread. */
    59 static void
    60 Initialize()
    61 {
    62     gInitialized = true;
    64     if (pthread_key_create(&gSelfThreadIndex, DummyDestructor)) {
    65         MOZ_CRASH();
    66         return;
    67     }
    69     pthread_setspecific(gSelfThreadIndex, &gMainThread);
    70 }
    72 PRThread *
    73 PR_CreateThread(PRThreadType type,
    74 		void (*start)(void *arg),
    75 		void *arg,
    76 		PRThreadPriority priority,
    77 		PRThreadScope scope,
    78 		PRThreadState state,
    79 		uint32_t stackSize)
    80 {
    81     JS_ASSERT(type == PR_USER_THREAD);
    82     JS_ASSERT(priority == PR_PRIORITY_NORMAL);
    84     if (!gInitialized) {
    85         /*
    86          * We assume that the first call to PR_CreateThread happens on the main
    87          * thread.
    88          */
    89         Initialize();
    90     }
    92     pthread_attr_t attr;
    93     if (pthread_attr_init(&attr))
    94         return nullptr;
    96     if (stackSize && pthread_attr_setstacksize(&attr, stackSize)) {
    97         pthread_attr_destroy(&attr);
    98         return nullptr;
    99     }
   101     nspr::Thread *t = js_new<nspr::Thread>(start, arg,
   102                                            state != PR_UNJOINABLE_THREAD);
   103     if (!t) {
   104         pthread_attr_destroy(&attr);
   105         return nullptr;
   106     }
   108     if (pthread_create(&t->pthread(), &attr, &nspr::Thread::ThreadRoutine, t)) {
   109         pthread_attr_destroy(&attr);
   110         js_delete(t);
   111         return nullptr;
   112     }
   114     if (state == PR_UNJOINABLE_THREAD) {
   115         if (pthread_detach(t->pthread())) {
   116             pthread_attr_destroy(&attr);
   117             js_delete(t);
   118             return nullptr;
   119         }
   120     }
   122     pthread_attr_destroy(&attr);
   124     return t;
   125 }
   127 PRStatus
   128 PR_JoinThread(PRThread *thread)
   129 {
   130     if (pthread_join(thread->pthread(), nullptr))
   131         return PR_FAILURE;
   133     js_delete(thread);
   135     return PR_SUCCESS;
   136 }
   138 PRThread *
   139 PR_GetCurrentThread()
   140 {
   141     if (!gInitialized)
   142         Initialize();
   144     return (PRThread *)pthread_getspecific(gSelfThreadIndex);
   145 }
   147 PRStatus
   148 PR_SetCurrentThreadName(const char *name)
   149 {
   150     int result;
   151 #ifdef XP_MACOSX
   152     result = pthread_setname_np(name);
   153 #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
   154     pthread_set_name_np(pthread_self(), name);
   155     result = 0;
   156 #elif defined(__NetBSD__)
   157     result = pthread_setname_np(pthread_self(), "%s", (void *)name);
   158 #else
   159     result = pthread_setname_np(pthread_self(), name);
   160 #endif
   161     if (result)
   162         return PR_FAILURE;
   163     return PR_SUCCESS;
   164 }
   166 static const size_t MaxTLSKeyCount = 32;
   167 static size_t gTLSKeyCount;
   168 static pthread_key_t gTLSKeys[MaxTLSKeyCount];
   170 PRStatus
   171 PR_NewThreadPrivateIndex(unsigned *newIndex, PRThreadPrivateDTOR destructor)
   172 {
   173     /*
   174      * We only call PR_NewThreadPrivateIndex from the main thread, so there's no
   175      * need to lock the table of TLS keys.
   176      */
   177     JS_ASSERT(PR_GetCurrentThread() == &gMainThread);
   179     pthread_key_t key;
   180     if (pthread_key_create(&key, destructor))
   181         return PR_FAILURE;
   183     JS_ASSERT(gTLSKeyCount + 1 < MaxTLSKeyCount);
   185     gTLSKeys[gTLSKeyCount] = key;
   186     *newIndex = gTLSKeyCount;
   187     gTLSKeyCount++;
   189     return PR_SUCCESS;
   190 }
   192 PRStatus
   193 PR_SetThreadPrivate(unsigned index, void *priv)
   194 {
   195     if (index >= gTLSKeyCount)
   196         return PR_FAILURE;
   197     if (pthread_setspecific(gTLSKeys[index], priv))
   198         return PR_FAILURE;
   199     return PR_SUCCESS;
   200 }
   202 void *
   203 PR_GetThreadPrivate(unsigned index)
   204 {
   205     if (index >= gTLSKeyCount)
   206         return nullptr;
   207     return pthread_getspecific(gTLSKeys[index]);
   208 }
   210 PRStatus
   211 PR_CallOnce(PRCallOnceType *once, PRCallOnceFN func)
   212 {
   213     MOZ_ASSUME_UNREACHABLE("PR_CallOnce unimplemented");
   214 }
   216 PRStatus
   217 PR_CallOnceWithArg(PRCallOnceType *once, PRCallOnceWithArgFN func, void *arg)
   218 {
   219     MOZ_ASSUME_UNREACHABLE("PR_CallOnceWithArg unimplemented");
   220 }
   222 class nspr::Lock
   223 {
   224     pthread_mutex_t mutex_;
   226   public:
   227     Lock() {}
   228     pthread_mutex_t &mutex() { return mutex_; }
   229 };
   231 PRLock *
   232 PR_NewLock()
   233 {
   234     nspr::Lock *lock = js_new<nspr::Lock>();
   235     if (!lock)
   236         return nullptr;
   238     if (pthread_mutex_init(&lock->mutex(), nullptr)) {
   239         js_delete(lock);
   240         return nullptr;
   241     }
   243     return lock;
   244 }
   246 void
   247 PR_DestroyLock(PRLock *lock)
   248 {
   249     pthread_mutex_destroy(&lock->mutex());
   250     js_delete(lock);
   251 }
   253 void
   254 PR_Lock(PRLock *lock)
   255 {
   256     pthread_mutex_lock(&lock->mutex());
   257 }
   259 PRStatus
   260 PR_Unlock(PRLock *lock)
   261 {
   262     if (pthread_mutex_unlock(&lock->mutex()))
   263         return PR_FAILURE;
   264     return PR_SUCCESS;
   265 }
   267 class nspr::CondVar
   268 {
   269     pthread_cond_t cond_;
   270     nspr::Lock *lock_;
   272   public:
   273     CondVar(nspr::Lock *lock) : lock_(lock) {}
   274     pthread_cond_t &cond() { return cond_; }
   275     nspr::Lock *lock() { return lock_; }
   276 };
   278 PRCondVar *
   279 PR_NewCondVar(PRLock *lock)
   280 {
   281     nspr::CondVar *cvar = js_new<nspr::CondVar>(lock);
   282     if (!cvar)
   283         return nullptr;
   285     if (pthread_cond_init(&cvar->cond(), nullptr)) {
   286         js_delete(cvar);
   287         return nullptr;
   288     }
   290     return cvar;
   291 }
   293 void
   294 PR_DestroyCondVar(PRCondVar *cvar)
   295 {
   296     pthread_cond_destroy(&cvar->cond());
   297     js_delete(cvar);
   298 }
   300 PRStatus
   301 PR_NotifyCondVar(PRCondVar *cvar)
   302 {
   303     if (pthread_cond_signal(&cvar->cond()))
   304         return PR_FAILURE;
   305     return PR_SUCCESS;
   306 }
   308 PRStatus
   309 PR_NotifyAllCondVar(PRCondVar *cvar)
   310 {
   311     if (pthread_cond_broadcast(&cvar->cond()))
   312         return PR_FAILURE;
   313     return PR_SUCCESS;
   314 }
   316 uint32_t
   317 PR_MillisecondsToInterval(uint32_t milli)
   318 {
   319     return milli;
   320 }
   322 static const uint64_t TicksPerSecond = 1000;
   323 static const uint64_t NanoSecondsInSeconds = 1000000000;
   324 static const uint64_t MicroSecondsInSeconds = 1000000;
   326 uint32_t
   327 PR_TicksPerSecond()
   328 {
   329     return TicksPerSecond;
   330 }
   332 PRStatus
   333 PR_WaitCondVar(PRCondVar *cvar, uint32_t timeout)
   334 {
   335     if (timeout == PR_INTERVAL_NO_TIMEOUT) {
   336         if (pthread_cond_wait(&cvar->cond(), &cvar->lock()->mutex()))
   337             return PR_FAILURE;
   338         return PR_SUCCESS;
   339     } else {
   340         struct timespec ts;
   341         struct timeval tv;
   343         gettimeofday(&tv, nullptr);
   344         ts.tv_sec = tv.tv_sec;
   345         ts.tv_nsec = tv.tv_usec * (NanoSecondsInSeconds / MicroSecondsInSeconds);
   347         ts.tv_nsec += timeout * (NanoSecondsInSeconds / TicksPerSecond);
   348         while (uint64_t(ts.tv_nsec) >= NanoSecondsInSeconds) {
   349             ts.tv_nsec -= NanoSecondsInSeconds;
   350             ts.tv_sec++;
   351         }
   353         int result = pthread_cond_timedwait(&cvar->cond(), &cvar->lock()->mutex(), &ts);
   354         if (result == 0 || result == ETIMEDOUT)
   355             return PR_SUCCESS;
   356         return PR_FAILURE;
   357     }
   358 }
   360 #endif /* JS_POSIX_NSPR */

mercurial