📄 bug1test.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*Attached is a test program that uses the nspr1 to demonstrate a bugunder NT4.0. The fix has already been mentioned (add a ResetEvent justbefore leaving the critical section in _PR_CondWait in hwmon.c).*/#include "prthread.h"#include "prtypes.h"#include "prinit.h"#include "prmon.h"#include "prlog.h"typedef struct Arg_s{ PRInt32 a, b;} Arg_t;PRMonitor* gMonitor; // the monitorPRInt32 gReading; // number of read locksPRInt32 gWriteWaiting; // number of threads waiting for write lockPRInt32 gReadWaiting; // number of threads waiting for read lockPRInt32 gCounter; // a counter // statsPRInt32 gReads; // number of successful readsPRInt32 gMaxReads; // max number of simultaneous readsPRInt32 gMaxWriteWaits; // max number of writes that waited for readPRInt32 gMaxReadWaits; // max number of reads that waited for write waitvoid spin (PRInt32 aDelay){ PRInt32 index; PRInt32 delay = aDelay * 1000; PR_Sleep(0); // randomize delay a bit delay = (delay / 2) + (PRInt32)((float)delay * ((float)rand () / (float)RAND_MAX)); for (index = 0; index < delay * 10; index++) // consume a bunch of cpu cycles ; PR_Sleep(0); }void doWriteThread (void* arg){ PRInt32 last; Arg_t *args = (Arg_t*)arg; PRInt32 aWorkDelay = args->a, aWaitDelay = args->b; PR_Sleep(0); while (1) { // -- enter write lock PR_EnterMonitor (gMonitor); if (0 < gReading) // wait for read locks to go away { PRIntervalTime fiveSecs = PR_SecondsToInterval(5); gWriteWaiting++; if (gWriteWaiting > gMaxWriteWaits) // stats gMaxWriteWaits = gWriteWaiting; while (0 < gReading) PR_Wait (gMonitor, fiveSecs); gWriteWaiting--; } // -- write lock entered last = gCounter; gCounter++; spin (aWorkDelay); PR_ASSERT (gCounter == (last + 1)); // test invariance // -- exit write lock // if (0 < gReadWaiting) // notify waiting reads (do it anyway to show off the CondWait bug) PR_NotifyAll (gMonitor); PR_ExitMonitor (gMonitor); // -- write lock exited spin (aWaitDelay); }}void doReadThread (void* arg){ PRInt32 last; Arg_t *args = (Arg_t*)arg; PRInt32 aWorkDelay = args->a, aWaitDelay = args->b; PR_Sleep(0); while (1) { // -- enter read lock PR_EnterMonitor (gMonitor); if (0 < gWriteWaiting) // give up the monitor to waiting writes { PRIntervalTime fiveSecs = PR_SecondsToInterval(5); gReadWaiting++; if (gReadWaiting > gMaxReadWaits) // stats gMaxReadWaits = gReadWaiting; while (0 < gWriteWaiting) PR_Wait (gMonitor, fiveSecs); gReadWaiting--; } gReading++; gReads++; // stats if (gReading > gMaxReads) // stats gMaxReads = gReading; PR_ExitMonitor (gMonitor); // -- read lock entered last = gCounter; spin (aWorkDelay); PR_ASSERT (gCounter == last); // test invariance // -- exit read lock PR_EnterMonitor (gMonitor); // read unlock gReading--;// if ((0 == gReading) && (0 < gWriteWaiting)) // notify waiting writes (do it anyway to show off the CondWait bug) PR_NotifyAll (gMonitor); PR_ExitMonitor (gMonitor); // -- read lock exited spin (aWaitDelay); }}void fireThread ( char* aName, void (*aProc)(void *arg), Arg_t *aArg){ PRThread *thread = PR_CreateThread( PR_USER_THREAD, aProc, aArg, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);}int pseudoMain (int argc, char** argv, char *pad){ PRInt32 lastWriteCount = gCounter; PRInt32 lastReadCount = gReads; Arg_t a1 = {500, 250}; Arg_t a2 = {500, 500}; Arg_t a3 = {250, 500}; Arg_t a4 = {750, 250}; Arg_t a5 = {100, 750}; Arg_t a6 = {100, 500}; Arg_t a7 = {100, 750}; gMonitor = PR_NewMonitor (); fireThread ("R1", doReadThread, &a1); fireThread ("R2", doReadThread, &a2); fireThread ("R3", doReadThread, &a3); fireThread ("R4", doReadThread, &a4); fireThread ("W1", doWriteThread, &a5); fireThread ("W2", doWriteThread, &a6); fireThread ("W3", doWriteThread, &a7); fireThread ("R5", doReadThread, &a1); fireThread ("R6", doReadThread, &a2); fireThread ("R7", doReadThread, &a3); fireThread ("R8", doReadThread, &a4); fireThread ("W4", doWriteThread, &a5); fireThread ("W5", doWriteThread, &a6); fireThread ("W6", doWriteThread, &a7); while (1) { PRInt32 writeCount, readCount; PRIntervalTime fiveSecs = PR_SecondsToInterval(5); PR_Sleep (fiveSecs); // get out of the way // print some stats, not threadsafe, informative only writeCount = gCounter; readCount = gReads; printf ("\ntick %d writes (+%d), %d reads (+%d) [max %d, %d, %d]", writeCount, writeCount - lastWriteCount, readCount, readCount - lastReadCount, gMaxReads, gMaxWriteWaits, gMaxReadWaits); lastWriteCount = writeCount; lastReadCount = readCount; gMaxReads = gMaxWriteWaits = gMaxReadWaits = 0; } return 0;}static void padStack (int argc, char** argv){ char pad[512]; /* Work around bug in nspr on windoze */ pseudoMain (argc, argv, pad);}void main (int argc, char **argv){ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); padStack (argc, argv);}/* bug1test.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -