You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: jsrc/ct.c
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -454,7 +454,7 @@ ASSERT(0,EVNONCE)
454
454
}elseif(m==2){
455
455
// return list of idle threads
456
456
ASSERT(AR(w)==1,EVRANK) ASSERT(AN(w)==0,EVLENGTH) // only '' is allowed as an argument for now
457
-
GAT0(z,INT,MAXTASKS,1) I*zv=IAV1(z); // Don't allocate under lock, and list may change: so allocate max possible
457
+
GA0(z,INT,MAXTASKS,1) I*zv=IAV1(z); // Don't allocate under lock, and list may change: so allocate max possible. Don't use GAT in case MAXTASKS is too big for it
458
458
Ithreadct=0; Jmjt=MTHREAD(JJTOJ(jt)); Jcurrjt=mjt; // # threads, master thread, current thread
459
459
WRITELOCK(mjt->tasklock); while(currjt->taskidleq){zv[threadct++]=currjt->taskidleq; currjt=JTFORTHREAD(jt,currjt->taskidleq);} WRITEUNLOCK(mjt->tasklock); // copy idle threads to result. The master can never be idle
Copy file name to clipboardExpand all lines: jsrc/jt.h
+12-13Lines changed: 12 additions & 13 deletions
Original file line number
Diff line number
Diff line change
@@ -88,7 +88,7 @@ typedef struct rngdata {
88
88
} us; // access as US
89
89
} uflags; // 4 bytes
90
90
// TASKCOMMREGION starts here, holding parms passed at startup
91
-
Ibytes; // bytes currently in use - used only during 7!:1 clear for task
91
+
Ibytesmax; // high-water mark of "bytes" - used only during 7!:1 clear for task
92
92
Setxn; // strlen(etx) but set negative to freeze changes to the error line clear for task
93
93
Setxn1; // last non-zero etxn clear for task
94
94
Bfoldrunning; // 1 if fold is running (allows Z:) clear for task
@@ -101,8 +101,6 @@ typedef struct rngdata {
101
101
Axmod; // extended integer: the m in m&|@f clear for task
102
102
// end of cacheline 0
103
103
// end of TASKCOMMREGION
104
-
// end of cacheline 0
105
-
Ibytesmax; // high-water mark of "bytes" - used only during 7!:1 clear for task
106
104
I4parsercalls; // # times parser was called clear for task
107
105
// ************************************** here starts the part that is initialized to non0 values when the task is started. Earlier values may also be initialized
108
106
UI4ranks; // low half: rank of w high half: rank of a for IRS init for task to 3F3F should be 2 bytes?
@@ -139,8 +137,8 @@ typedef struct rngdata {
139
137
140
138
Ishapesink[SY_64?2:4]; // garbage area used as load/store targets of operations we don't want to branch around. While waiting for work, this holds the address of the WAITBLOK we are waiting on
141
139
// things needed for allocation of large blocks
142
-
Imfreegenallo; // Amount allocated through malloc, biased
143
-
Imalloctotal; // net total of malloc/free performed in m.c only
140
+
A*tstacknext; // if not 0, points to the recently-used tstack buffer, whose chain field points to tstacknext
141
+
A*tstackcurr; // current allocation, holding NTSTACK bytes+1 block for alignment. First entry points to next-lower allocation
144
142
PFRAMEparserstackframe; // 4 words
145
143
// end of cacheline 4
146
144
@@ -155,18 +153,12 @@ typedef struct rngdata {
155
153
Imalloctotalhwmk; // highest value since most recent 7!:1
156
154
// end of cacheline 5
157
155
158
-
A*tstacknext; // if not 0, points to the recently-used tstack buffer, whose chain field points to tstacknext
159
-
A*tstackcurr; // current allocation, holding NTSTACK bytes+1 block for alignment. First entry points to next-lower allocation
156
+
// seldom used, but contended during system lock
160
157
C*etx; // [1+NETX]; // display text for last error (+1 for trailing 0)
161
158
void*dtoa; /* use internally by dtoa.c */
162
159
PSTKinitparserstack[1]; // stack used for messages when we don't have a real one
163
160
I4getlasterror; // DLL error info from previous DLL call
164
161
I4dlllasterror; // DLL domain error info (before DLL call)
165
-
Ifiller6[1];
166
-
// end of cacheline 6
167
-
168
-
// Area used for intertask communication
169
-
Arepatq[-PMINL+PLIML+1]; // queue of blocks allocated in this thread but freed by other threads. Used as a lock, so put in its own cacheline. We have 5 queues to avoid muxing; could do with 1
170
162
Staskidleq; // thread#s of the tasks waiting for work. Root of the idle chain is in the master.
171
163
Stasklock; // lock for taskidleq. Used only in master
172
164
Staskstate; // task state: modified by other tasks on a system lock
@@ -181,6 +173,13 @@ typedef struct rngdata {
181
173
#else
182
174
Ifiller7[2];
183
175
#endif
176
+
// end of cacheline 6
177
+
178
+
// Area used for intertask communication of memory allocation
179
+
Arepatq[-PMINL+PLIML+1]; // queue of blocks allocated in this thread but freed by other threads. Used as a lock, so put in its own cacheline. We have 5 queues to avoid muxing; could do with 1
180
+
Ibytes; // bytes currently in use - used only during 7!:1
181
+
Imfreegenallo; // Amount allocated through malloc, biased
182
+
Imalloctotal; // net total of malloc/free performed in m.c only
184
183
// end of cacheline 7
185
184
// stats I totalpops;
186
185
// stats I nonnullpops;
@@ -342,7 +341,7 @@ typedef struct JSTstruct {
342
341
typedefJST*JS; // shared part of struct
343
342
344
343
// When the task is not running, part of the per-call area is used as a communication region to hold parameters:
345
-
#defineTASKCOMMREGION(jt) ((void **)(&jt->bytes)) // [0..3] are parms, each a (void *)
344
+
#defineTASKCOMMREGION(jt) ((void **)(&jt->bytesmax)) // [0..3] are parms, each a (void *)
346
345
#defineTASKAWAITBLOK(jt) (*(void **)&jt->shapesink) // pointer to WAITBLOK in a waiting task
__atomic_fetch_sub(&jt->mfreegenallo,TAILPAD,__ATOMIC_ACQ_REL); // remove pad from the amount we report allocated
283
283
#endif
284
284
}else{AFHRH(baseblock) =virginbase;} // restore the count to 0 in the rest
285
285
p=np; // step to next base block
@@ -292,7 +292,7 @@ B jtspfree(J jt){I i;A p;
292
292
// compensated for by a change to mfreegenallo. mfreegenallo must also account for the excess padding that is now being returned
293
293
// This elides the step of subtracting coalesced buffers from the number of allocated buffers of size i, followed by
294
294
// adding the bytes for those blocks to mfreebgenallo
295
-
jt->mfreegenallo-=SBFREEB- (jt->mfree[i].ballo& ~MFREEBCOUNTING); // subtract diff between current mfreeb[] and what it will be set to
295
+
__atomic_fetch_sub(&jt->mfreegenallo,SBFREEB- (jt->mfree[i].ballo& ~MFREEBCOUNTING),__ATOMIC_ACQ_REL); // subtract diff between current mfreeb[] and what it will be set to
296
296
jt->mfree[i].ballo=SBFREEB+ (jt->mfree[i].ballo&MFREEBCOUNTING); // set so we trigger rescan when we have allocated another SBFREEB bytes
297
297
}
298
298
}
@@ -418,7 +418,7 @@ R totalallo;
418
418
// Also count current space, and set that into jt->bytes and the result of this function
// There is no way two allocations could back up so as to make the end of one exactly the beginning of the other
1086
1086
if((A*)np!=pushp-1){
1087
1087
// if there is another block in this allocation, step to it. Otherwise:
1088
-
if(jt->tstacknext){FREECHK(jt->tstacknext); jt->malloctotal-=NTSTACK+NTSTACKBLOCK;} // account for malloc'd memory
1088
+
if(jt->tstacknext){FREECHK(jt->tstacknext); __atomic_fetch_sub(&jt->malloctotal,NTSTACK+NTSTACKBLOCK,__ATOMIC_ACQ_REL);} // account for malloc'd memory
1089
1089
// We will set the block we are vacating as the next-to-use. We can have only 1 such; if there is one already, free it
1090
1090
jt->tstacknext=jt->tstackcurr; // save the next-to-use, after removing bias
1091
1091
jt->tstackcurr=(A*)jt->tstackcurr[0]; // back up to the previous block
@@ -1135,8 +1135,8 @@ __attribute__((noinline)) A jtgafallopool(J jt,I blockx,I n){
1135
1135
// allocate without alignment
1136
1136
ASSERT(av=MALLOC(PSIZE+TAILPAD),EVWSFULL);
1137
1137
#endif
1138
-
Int=jt->malloctotal+=PSIZE+TAILPAD+ALIGNPOOLTOCACHE*CACHELINESIZE; // add to total JE mem allocated
1139
-
jt->mfreegenallo+=PSIZE+TAILPAD+ALIGNPOOLTOCACHE*CACHELINESIZE; // ...add them to the total bytes allocated drom OS
1138
+
Int=__atomic_add_fetch(&jt->malloctotal,PSIZE+TAILPAD+ALIGNPOOLTOCACHE*CACHELINESIZE,__ATOMIC_ACQ_REL); // add to total JE mem allocated
1139
+
__atomic_fetch_add(&jt->mfreegenallo,PSIZE+TAILPAD+ALIGNPOOLTOCACHE*CACHELINESIZE,__ATOMIC_ACQ_REL); // ...add them to the total bytes allocated drom OS
A*tp=jt->tnextpushp; AZAPLOC(z)=tp; *tp++=z; jt->tnextpushp=tp; if(unlikely(((I)tp&(NTSTACKBLOCK-1))==0))RZ(z=jttgz(jt,tp,z)); // do the tpop/zaploc chaining
A*tp=jt->tnextpushp; AZAPLOC(z)=tp; *tp++=z; jt->tnextpushp=tp; if(unlikely(((I)tp&(NTSTACKBLOCK-1))==0))RZ(z=jttgz(jt,tp,z)); // do the tpop/zaploc chaining
1184
1185
#ifPYXES
1185
-
z->lock=0; // init lock on the block to 'available'
1186
+
*(I4*)&z->origin=THREADID(jt); // init allocating thread# and clear the lock
1187
+
// obsolete z->lock=0; // init lock on the block to 'available'
1186
1188
#endif
1187
1189
Rz;
1188
1190
}
@@ -1213,7 +1215,8 @@ if((I)jt&3)SEGFAULT;
1213
1215
jt->mfree[-PMINL+1+blockx].pool=AFCHAIN(z); // remove & use the head of the free chain
1214
1216
// If the user is keeping track of memory high-water mark with 7!:2, figure it out & keep track of it. Otherwise save the cycles. All allo routines must do this
0 commit comments