set executable bit on promote-build.sh (r=cpeyer)
[tamarin-stm.git] / extensions / ST_mmgc_threads.cpp
blob2bc9c4cccc53e70bd66fbf5b85b1d2ce75a0a7d4
1 // Generated from ST_mmgc_threads.st
2 // -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
3 // vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
4 //
5 // ***** BEGIN LICENSE BLOCK *****
6 // Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 //
8 // The contents of this file are subject to the Mozilla Public License Version
9 // 1.1 (the "License"); you may not use this file except in compliance with
10 // the License. You may obtain a copy of the License at
11 // http://www.mozilla.org/MPL/
13 // Software distributed under the License is distributed on an "AS IS" basis,
14 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 // for the specific language governing rights and limitations under the
16 // License.
18 // The Original Code is [Open Source Virtual Machine.].
20 // The Initial Developer of the Original Code is
21 // Adobe System Incorporated.
22 // Portions created by the Initial Developer are Copyright (C) 2004-2006
23 // the Initial Developer. All Rights Reserved.
25 // Contributor(s):
26 // Adobe AS3 Team
28 // Alternatively, the contents of this file may be used under the terms of
29 // either the GNU General Public License Version 2 or later (the "GPL"), or
30 // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 // in which case the provisions of the GPL or the LGPL are applicable instead
32 // of those above. If you wish to allow use of your version of this file only
33 // under the terms of either the GPL or the LGPL, and not to allow others to
34 // use your version of this file under the terms of the MPL, indicate your
35 // decision by deleting the provisions above and replace them with the notice
36 // and other provisions required by the GPL or the LGPL. If you do not delete
37 // the provisions above, a recipient may use your version of this file under
38 // the terms of any one of the MPL, the GPL or the LGPL.
40 // ***** END LICENSE BLOCK ***** */
42 #include "avmshell.h"
43 #ifdef VMCFG_SELFTEST
44 #if defined VMCFG_WORKERTHREADS
45 namespace avmplus {
46 class ST_mmgc_threads : public Selftest {
47 public:
48 ST_mmgc_threads(AvmCore* core);
49 virtual void run(int n);
50 virtual void prologue();
51 virtual void epilogue();
52 private:
53 static const char* ST_names[];
54 static const bool ST_explicits[];
55 void test0();
57 private:
58 MMgc::GC *gc;
59 MMgc::FixedAlloc *fa;
60 MMgc::FixedMalloc *fm;
61 bool waiting;
62 bool result;
63 bool isDead;
64 pthread_t pthread;
65 pthread_mutex_t pmutex;
66 pthread_cond_t pcond;
68 static void* slaveRunner(void *arg)
70 ((ST_mmgc_threads*)arg)->slaveRun();
71 return NULL;
74 void slaveRun()
76 wait();
78 MMGC_ENTER_VOID;
79 MMGC_GCENTER(gc);
80 result &= !isDead;
81 gc->ReapZCT();
82 result &= !isDead;
83 gc->Collect();
84 result &= !isDead;
86 kick();
89 void startSlave()
91 pthread_create(&pthread, NULL, slaveRunner, this);
94 void kick()
96 pthread_mutex_lock (&pmutex);
97 while(!waiting) {
98 pthread_mutex_unlock (&pmutex);
99 usleep(100);
100 pthread_mutex_lock (&pmutex);
102 pthread_cond_signal (&pcond);
103 while(waiting) {
104 pthread_mutex_unlock (&pmutex);
105 usleep(100);
106 pthread_mutex_lock (&pmutex);
108 pthread_mutex_unlock (&pmutex);
111 void wait()
113 pthread_mutex_lock (&pmutex);
114 GCAssert(waiting == false);
115 waiting = true;
116 pthread_cond_wait (&pcond, &pmutex);
117 waiting = false;
118 pthread_mutex_unlock (&pmutex);
121 static void kickAndWait(void* arg)
123 ST_mmgc_threads* self = (ST_mmgc_threads*)arg;
124 self->kick();
125 self->wait();
129 ST_mmgc_threads::ST_mmgc_threads(AvmCore* core)
130 : Selftest(core, "mmgc", "threads", ST_mmgc_threads::ST_names,ST_mmgc_threads::ST_explicits)
132 const char* ST_mmgc_threads::ST_names[] = {"mmgc_gc_root_thread", NULL };
133 const bool ST_mmgc_threads::ST_explicits[] = {false, false };
134 void ST_mmgc_threads::run(int n) {
135 switch(n) {
136 case 0: test0(); return;
139 void ST_mmgc_threads::prologue() {
140 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), MMgc::GC::kIncrementalGC);
141 if (gc==NULL) {
142 MMgc::GCHeap::Init();
143 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), MMgc::GC::kIncrementalGC);
145 pthread_mutex_init(&pmutex, NULL);
146 pthread_cond_init(&pcond, NULL);
147 result = true;
148 isDead = false;
149 waiting = false;
152 void ST_mmgc_threads::epilogue() {
153 pthread_mutex_destroy(&pmutex);
154 pthread_cond_destroy(&pcond);
155 delete gc;
158 using namespace MMgc;
160 class RCObjectNotifier : public RCObject
162 public:
163 RCObjectNotifier(bool *isDead) : isDead(isDead) {}
164 ~RCObjectNotifier() { *isDead = true; isDead = NULL; }
165 bool *isDead;
168 void ST_mmgc_threads::test0() {
169 startSlave();
170 MMGC_GCENTER(gc);
171 RCObjectNotifier *obj = new (gc) RCObjectNotifier(&isDead);
173 gc->CreateRootFromCurrentStack(kickAndWait, this);
176 #line 154 "ST_mmgc_threads.st"
177 verifyPass(result, "result", __FILE__, __LINE__);
179 #line 156 "ST_mmgc_threads.st"
180 verifyPass(!isDead, "!isDead", __FILE__, __LINE__);
181 gc->ReapZCT();
182 #line 158 "ST_mmgc_threads.st"
183 verifyPass(!isDead, "!isDead", __FILE__, __LINE__);
184 gc->Collect();
185 #line 160 "ST_mmgc_threads.st"
186 verifyPass(!isDead, "!isDead", __FILE__, __LINE__);
188 pthread_join(pthread, NULL);
190 printf("Ignore this: %d\n", *obj->isDead);
193 void create_mmgc_threads(AvmCore* core) { new ST_mmgc_threads(core); }
195 #endif
196 #endif