dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / lib / spu / FastCommunication.cpp
1 /*
2  * FastCommunication.cpp
3  *
4  *  Created on: Mar 3, 2009
5  *      Author: lschor
6  *
7  * Provides the communication between various processors.
8  *
9  *
10  *
11  * Description:
12  *
13  * Sender: The processor now has some data that need to be forwarded
14  * to another processor.
15  * Receiver: The processor that needs to get the data.
16  *
17  * Sender ----                                                      *
18  *            -----> Have some data                                 *
19  *                   (Len, queue)                                   *
20  *                                 ----------->        Receiver     *
21  *                                                                  *
22  *                                                  Check its len   *
23  *                                                                  *
24  *                                                  Sets up a DMA   *
25  *                                                  transfer to     *
26  *                                                  read from the   *
27  *                                 <--------------  queue to a      *
28  *                  MFC performs the                local buffer    *
29  *                  transfer                        (Alignment)     *
30  *       <---------                                                 *
31  *                                                                  *
32  *                                                                  *
33  *                                                  (Pools if the   *
34  *                                                   transfer is    *
35  *                                                   completed)     *
36  *                                                                  *
37  *                                                                  *
38  *                                                  Copy the data   *
39  *                                                  from its temp.  *
40  *                                                  buffer to the   *
41  *                                                  queue und       *
42  *                    Have completed <------------  informs the     *
43  *       <---------- (queue, len)                 sender            *
44  * Can increase the                                                 *
45  * pointers in the FIFO
46  *
47  *
48  * Has two ways to handling request, which are not possible
49  * to work out currently:
50  *  1) Send back "len = 0"
51  *     --> Needs to send more messages, but may bigger lens
52  *  2) Store them until you have enough space to read
53  *     --> Smaller lens and less messages
54  */
55
56 #include "FastCommunication.h"
57
58 /*
59  * Constructor
60  */
61 FastCommunication::FastCommunication(int nrOfQueues, uint64_t ea_base,
62                 uint64_t *ea_base_all, int32_t * queueFromSPEIn,
63                 int32_t * queueOnSPEIn, uint64_t *fifoTails) {
64
65         // Set the base address
66         _ea_base = ea_base;
67
68         _ea_base_all = ea_base_all;
69         queueFromSPE = queueFromSPEIn;
70         queueOnSPE = queueOnSPEIn;
71         _fifoTails = fifoTails;
72
73         _nrOfQueues = nrOfQueues;
74         try { _fifos = new fifoCollection[nrOfQueues]; }
75         catch(std::bad_alloc &e) {
76             fprintf(stderr, "[FastCommunication] Memory allocation failure\n");
77             exit(1);
78         }
79         _nrOfRequest = 0;
80
81         for (int i = 0; i < MAXNOREQ; i++) {
82                 _request[i].valid = false;
83         }
84 }
85
86 /*
87  * Deconstructor
88  */
89 FastCommunication::~FastCommunication() {
90         delete _fifos;
91 }
92
93 /*
94  * Register an additional FIFO in the Communication
95  */
96 bool FastCommunication::addFifo(int fifoNr, Fifo* fifo, int type,
97                 int queue) {
98         _fifos[fifoNr].fifo = fifo;
99         _fifos[fifoNr].queue = queue;
100         _fifos[fifoNr].type = type;
101         _fifos[fifoNr].iswfifo = false;
102
103         // Per FIFO queue, we need two requests, but we store at max MAXNOREQ of them
104         if (_nrOfRequest < MAXNOREQ) {
105                 _nrOfRequest += 2;
106         }
107
108         return true;
109 }
110
111 /*
112  * Register an additional WindowedFIFO in the Communication
113  */
114 bool FastCommunication::addWFifo(int fifoNr, WindowedFifo* wfifo,
115                 int type, int queue) {
116         _fifos[fifoNr].wfifo = wfifo;
117         _fifos[fifoNr].queue = queue;
118         _fifos[fifoNr].type = type;
119         _fifos[fifoNr].iswfifo = true;
120
121         // Per FIFO queue, we need two requests, but we store at max MAXNOREQ of them
122         if (_nrOfRequest < MAXNOREQ) {
123                 _nrOfRequest += 2;
124         }
125
126         return true;
127 }
128
129 /*
130  * Communication: Main update procedure to update
131  */
132 bool FastCommunication::update() {
133         // Check if you have received a new message
134         while (spu_stat_in_mbox() > 0) {
135                 uint32_t messageIn = spu_read_in_mbox();
136
137                 uint32_t code = GETFASTCODE(messageIn);
138                 uint32_t queue = GETFASTQUEUE(messageIn);
139                 uint32_t len = GETFASTLEN(messageIn);
140
141                 /***************************************************************************************************************/
142                 if (code == SPE_READ_DEMAND) // One should start a read process
143                 {
144                         // Find out for which fifo the request is
145                         fifoCollection *fifocol = NULL;
146                         int i = 0;
147                         for (i = 0; i < _nrOfQueues; i++) {
148                                 if (_fifos[i].queue == queue) {
149                                         fifocol = &_fifos[i];
150                                         break;
151                                 }
152                         }
153
154                         // The queue was not found
155                         if (fifocol == NULL) {
156                                 printf("SPU COM> ERROR, this queue does not exists!\n");
157                                 return false;
158                         }
159
160                         // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161                         // Windowed FIFO
162                         if (_fifos[i].iswfifo) {
163
164                                 WindowedFifo* wfifo = NULL;
165                                 wfifo = _fifos[i].wfifo;
166
167                                 // Find the current tail of the queue from where to read
168                                 uint32_t inTail = wfifo->_inTail;
169
170                                 // This is the len we like to read
171                                 len = len > (wfifo->unused()) ? wfifo->unused() : len;
172
173                                 // We can read something
174                                 if (len > 0) {
175                                         // Write all information we used to the request-memory
176                                         comRequest* request = newRequest();
177
178                                         // Has no memory to store a new request
179                                         if (request == NULL) {
180                                                 // not possible to start a request for this SPE --> Send len = 0
181                                                 uint32_t message = CREATEFASTMESSAGE(
182                                                                 SPE_READ_COMPLETE, queue, 0);
183                                                 sendMessage(message, queueFromSPE[queue]);
184                                                 return false;
185                                         }
186
187                                         // reserve DMA tag ID
188                                         uint32_t tag_id;
189                                         if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
190                                                 printf("SPE: ERROR - can't reserve a tag ID\n");
191                                                 return false;
192                                         }
193
194                                         // Generate the base address of the input FIFO
195                                         uint64_t baseAddress = _fifoTails[queue] + inTail;
196
197                                         // Align the address to the correct factor (in general 128 or 32)
198                                         while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
199                                                 baseAddress--;
200
201                                         // Offset --> How much we had to align
202                                         uint32_t offset = _fifoTails[queue] + inTail
203                                                         - baseAddress;
204
205                                         request->data = (char *) _malloc_align(roundDMA(len
206                                                         + offset), ALIGNMENT_FACTOR);
207
208                                         // Store all data in the request buffer
209                                         request->len = len;
210
211                                         request->wfifo = wfifo;
212                                         request->iswfifo = true;
213
214                                         request->status = read_started;
215                                         request->queue = queue;
216                                         request->offset = offset;
217                                         request->tag_id = tag_id;
218
219                                         // Set up the request in the MFC
220                                         mfc_get((void *) &(request->data[0]), baseAddress,
221                                                         roundDMA(len + offset), tag_id, 0, 0);
222                                 }
223
224                                 else {
225 #ifndef STORE_REQUESTS                // Send len = 0 back to the sender, this one should try it in a later phase
226                                         uint32_t message = CREATEFASTMESSAGE(
227                                                         SPE_READ_COMPLETE, queue, 0);
228                                         sendMessage(message, queueFromSPE[queue]);
229 #else                                // I store the request and may try in a later time to start the transfer
230                                         comRequest* request = newRequest();
231
232                                         // Has no memory to store a new request
233                                         if (request == NULL)
234                                         {
235                                                 // not possible to start a request for this SPE --> Send len = 0
236                                                 uint32_t message = CREATEFASTMESSAGE(SPE_READ_COMPLETE, queue, 0);
237                                                 sendMessage(message, queueFromSPE[queue]);
238                                                 return false;
239                                         }
240
241                                         request->len = len;
242                                         request->wfifo = wfifo;
243                                         request->iswfifo = true;
244                                         request->status = read_pending;
245                                         request->queue = queue;
246 #endif
247                                 }
248                         }
249
250                         // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251                         // Classic FIFO
252                         else {
253                                 Fifo* fifo = NULL;
254                                 fifo = _fifos[i].fifo;
255
256                                 uint32_t inTail = fifo->_inTail;
257
258                                 // This is the len we like to read
259                                 len = len > (fifo->unused()) ? fifo->unused() : len;
260
261                                 // We can read something
262                                 if (len > 0) {
263                                         // Write all information we used to the request-memory
264                                         comRequest* request = newRequest();
265
266                                         // Has no memory to store a new request
267                                         if (request == NULL) {
268                                                 // not possible to start a request for this SPE --> Send len = 0
269                                                 uint32_t message = CREATEFASTMESSAGE(
270                                                                 SPE_READ_COMPLETE, queue, 0);
271                                                 sendMessage(message, queueFromSPE[queue]);
272                                                 return false;
273                                         }
274
275                                         uint32_t tag_id;
276
277                                         // reserve DMA tag ID
278                                         if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
279                                                 printf("SPE: ERROR - can't reserve a tag ID\n");
280                                                 return false;
281                                         }
282
283                                         uint64_t baseAddress = _fifoTails[queue] + inTail;
284
285                                         while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
286                                                 baseAddress--;
287
288                                         // Offset
289                                         uint32_t offset = _fifoTails[queue] + inTail
290                                                         - baseAddress;
291
292                                         // Store all data in the request buffer
293                                         request->data = (char *) _malloc_align(roundDMA(len
294                                                         + offset), ALIGNMENT_FACTOR);
295                                         request->len = len;
296                                         request->fifo = fifo;
297                                         request->iswfifo = false;
298                                         request->status = read_started;
299                                         request->queue = queue;
300                                         request->offset = offset;
301                                         request->tag_id = tag_id;
302
303                                         // Tell the fifo that one has reserved some data
304
305                                         mfc_get((void *) &(request->data[0]), baseAddress,
306                                                         roundDMA(len + offset), tag_id, 0, 0);
307                                 }
308
309                                 // len == 0
310                                 else {
311 #ifndef STORE_REQUESTS                // Send len = 0 back to the sender, this one should try it in a later phase
312                                         uint32_t message = CREATEFASTMESSAGE(
313                                                         SPE_READ_COMPLETE, queue, 0);
314                                         sendMessage(message, queueFromSPE[queue]);
315 #else                                // I store the request and may try in a later time to start the transfer
316                                         comRequest* request = newRequest();
317
318                                         // Has no memory to store a new request
319                                         if (request == NULL)
320                                         {
321                                                 // not possible to start a request for this SPE --> Send len = 0
322                                                 uint32_t message = CREATEFASTMESSAGE(SPE_READ_COMPLETE, queue, 0);
323                                                 sendMessage(message, queueFromSPE[queue]);
324                                                 return false;
325                                         }
326
327                                         request->len = len;
328                                         request->fifo = fifo;
329                                         request->iswfifo = false;
330                                         request->status = read_pending;
331                                         request->queue = queue;
332 #endif
333                                 }
334                         }
335                 }
336
337                 /***************************************************************************************************************/
338                 else if (code == SPE_READ_COMPLETE) // A read has finished
339                 {
340                         // Get the stored request
341                         comRequest* request = getRequest(read_request_sent, queue);
342                         if (request == NULL) {
343                                 printf(
344                                                 ">>>>>>>>>>>>>>>>> Communicate SPU> Couldn't find the request\n");
345                                 return 0;
346                         }
347
348                         // Inform my FIFO that the request is completed
349                         if (request->iswfifo)
350                                 request->wfifo->dmaRead(len);
351                         else
352                                 request->fifo->dmaRead(len);
353
354                         // Request free
355                         deleteRequest(request);
356                 }
357         }
358
359         /***************************************************************************************************************/
360         // Check if some active write processes have finished
361         uint8_t req = _currentRequest;
362
363         for (int i = 0; i < _nrOfRequest; i++) // Check all possible requests
364         {
365                 if (_request[req].valid) // Only to check if the request is valid
366                 {
367                         if (_request[req].status == read_started) { // We have setup the request, now check if it is complete
368
369                                 // If I cannot send a message to the corresponding processor --> Do not have to check it
370                                 if (!(testMessage(queueOnSPE[_request[req].queue]) > 0))
371                                         continue;
372
373                                 // Check if the specific Tag-ID has completed
374                                 uint32_t tag_id = _request[req].tag_id;
375                                 mfc_write_tag_mask(1 << tag_id);
376                                 mfc_write_tag_update(MFC_TAG_UPDATE_IMMEDIATE);
377                                 uint32_t ret = mfc_read_tag_status();
378
379                                 if (!((ret & (1 << tag_id)) == 0)) {
380
381                                         // This update is finished
382                                         mfc_tag_release(tag_id);
383
384                                         // Have to write the data into the fifo
385                                         if (_request[req].iswfifo) { // WFIFO
386
387                                                 _request[req].wfifo->dmaWrite(
388                                                                 (char *) _request[req].data
389                                                                                 + _request[req].offset,
390                                                                 _request[req].len);
391                                                 _free_align(_request[req].data);
392
393                                                 // Increase the inTail value (used to know where the last request was started)
394                                                 _request[req].wfifo->_inTail
395                                                                 = (_request[req].wfifo->_inTail
396                                                                                 + _request[req].len) % (FIFO_SIZE[_request[req].queue]);
397                                         } else { // FIFO
398                                                 _request[req].fifo->write(
399                                                                 (char *) _request[req].data
400                                                                                 + _request[req].offset,
401                                                                 _request[req].len);
402                                                 _free_align(_request[req].data);
403
404                                                 _request[req].fifo->_inTail
405                                                                 = (_request[req].fifo->_inTail
406                                                                                 + _request[req].len) % (FIFO_SIZE[_request[req].queue]);
407
408                                         }
409
410                                         // Inform the sender about the event
411                                         uint32_t message = CREATEFASTMESSAGE(
412                                                         SPE_READ_COMPLETE, _request[req].queue,
413                                                         _request[req].len);
414                                         sendMessage(message, queueFromSPE[_request[req].queue]);
415
416                                         // Delete the request
417                                         deleteRequest(&_request[req]);
418                                         _currentRequest = (req + 1) % _nrOfRequest;
419
420                                         break; // continue is also working
421                                 }
422                         } else if (_request[req].status == read_pending) { // Has an open request for sending
423
424                                 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425                                 // Windowed FIFO
426                                 if (_request[req].iswfifo) {
427
428                                         if (_request[req].wfifo->unused() > 0) {
429                                                 comRequest *request = &_request[req];
430
431                                                 // This is the len we like to read
432                                                 uint32_t len =  request->len > (request->wfifo->unused()) ? request->wfifo->unused()
433                                                                         : request->len;
434
435                                                 // reserve DMA tag ID
436                                                 uint32_t tag_id;
437                                                 if ((tag_id = mfc_tag_reserve())
438                                                                 == MFC_TAG_INVALID) {
439                                                         printf("SPE: ERROR - can't reserve a tag ID\n");
440                                                         return false;
441                                                 }
442
443                                                 uint32_t inTail = request->wfifo->_inTail;
444                                                 uint64_t baseAddress = _fifoTails[request->queue]
445                                                                 + inTail;
446
447                                                 while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
448                                                         baseAddress--;
449
450                                                 // Offset --> How much we had to align
451                                                 uint32_t offset = _fifoTails[request->queue]
452                                                                 + inTail - baseAddress;
453
454                                                 request->data = (char *) _malloc_align(roundDMA(
455                                                                 len + offset), ALIGNMENT_FACTOR);
456                                                 request->len = len;
457                                                 request->status = read_started;
458                                                 request->offset = offset;
459                                                 request->tag_id = tag_id;
460
461                                                 // Set up the request in the MFC
462                                                 mfc_get((void *) &(request->data[0]), baseAddress,
463                                                                 roundDMA(len + offset), tag_id, 0, 0);
464                                         }
465                                 }
466
467                                 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
468                                 // Classic FIFO
469                                 else {
470
471                                         if (_request[req].fifo->unused() > 0) {
472                                                 comRequest *request = &_request[req];
473
474                                                 // This is the len we like to read
475                                                 uint32_t len = request->len > (request->fifo->unused()) ? request->fifo->unused()
476                                                                         : request->len;
477
478                                                 uint32_t tag_id;
479                                                 // reserve DMA tag ID
480                                                 if ((tag_id = mfc_tag_reserve())
481                                                                 == MFC_TAG_INVALID) {
482                                                         printf("SPE: ERROR - can't reserve a tag ID\n");
483                                                         return false;
484                                                 }
485
486                                                 uint32_t inTail = request->fifo->_inTail;
487                                                 uint64_t baseAddress = _fifoTails[request->queue] + inTail;
488
489                                                 while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
490                                                         baseAddress--;
491
492                                                 // Offset
493                                                 uint32_t offset = _fifoTails[request->queue]
494                                                                 + inTail - baseAddress;
495
496                                                 // Store all data in the request buffer
497                                                 request->data = (char *) _malloc_align(roundDMA(
498                                                                 len + offset), ALIGNMENT_FACTOR);
499                                                 request->len = len;
500                                                 request->status = read_started;
501                                                 request->offset = offset;
502                                                 request->tag_id = tag_id;
503
504                                                 // Start the DMA transfer
505                                                 mfc_get((void *) &(request->data[0]), baseAddress,
506                                                                 roundDMA(len + offset), tag_id, 0, 0);
507                                         }
508                                 }
509                         }
510                 }
511                 // Go to the next Request
512                 req = (req + 1) % _nrOfRequest;
513         }
514
515         /***************************************************************************************************************/
516         // Start a new request to the receiver of a FIFO
517         for (int i = 0; i < _nrOfQueues; i++) {
518                 if (_fifos[i].type == this->out) // Only out-FIFO have to be quecked
519                 {
520                         if (_fifos[i].iswfifo) { // WFIFO
521
522                                 // Start only a write process if there is really enough place in the outbound mailbox
523                                 if (_fifos[i].wfifo->dmaAllowed() && _fifos[i].wfifo->used() > 0) {
524                                         uint32_t queue = _fifos[i].queue;
525
526                                         // Can we send a message to this processor or is it blocked?
527                                         if (testMessage(queueOnSPE[queue]) <= 0) {
528                                                 continue;
529                                         }
530
531                                         // Write all information we used to the request-memory
532                                         comRequest* request = newRequest();
533
534                                         // Has no memory to store a new request
535                                         if (request == NULL) {
536                                         } else {
537                                                 uint32_t len = _fifos[i].wfifo->dmaStart();
538                                                 // Create a write-demand message
539                                                 uint32_t message = CREATEFASTMESSAGE(
540                                                                 SPE_READ_DEMAND, queue, len);
541
542                                                 request->len = len;
543                                                 request->queue = queue;
544                                                 request->status = read_request_sent;
545                                                 request->wfifo = _fifos[i].wfifo;
546                                                 request->iswfifo = true;
547
548                                                 sendMessage(message, queueOnSPE[queue]);
549                                         }
550                                         break;
551                                 }
552                         } else { // FIFO
553
554                                 // Start only a write process if there is really enough place in the outbound mailbox
555                                 if (_fifos[i].fifo->dmaAllowed() && _fifos[i].fifo->used() > 0) {
556                                         uint32_t queue = _fifos[i].queue;
557
558                                         // Check if we can send a message to the processor
559                                         if (testMessage(queueOnSPE[queue]) <= 0) {
560                                                 continue;
561                                         }
562
563                                         // Write all information we used to the request-memory
564                                         comRequest* request = newRequest();
565
566                                         // Has no memory to store a new request
567                                         if (request == NULL) {
568                                         } else {
569                                                 uint32_t len = _fifos[i].fifo->dmaStart();
570                                                 // Create a write-demand message
571                                                 uint32_t message = CREATEFASTMESSAGE(
572                                                                 SPE_READ_DEMAND, queue, len);
573
574                                                 request->len = len;
575                                                 request->queue = queue;
576                                                 request->status = read_request_sent;
577                                                 request->fifo = _fifos[i].fifo;
578                                                 request->iswfifo = false;
579
580                                                 sendMessage(message, queueOnSPE[queue]);
581                                         }
582                                         break;
583                                 }
584                         }
585                 }
586         }
587         return true;
588 }
589
590 /*
591  * Create a new request to store in the cache
592  *
593  */
594 comRequest* FastCommunication::newRequest() {
595         for (int i = 0; i < _nrOfRequest; i++) {
596                 if (!_request[i].valid) {
597                         _request[i].valid = true;
598                         return &(_request[i]);
599                 }
600         }
601
602         return NULL;
603 }
604
605 /*
606  * Delete the request
607  *
608  */
609 void FastCommunication::deleteRequest(comRequest* request) {
610         request->valid = false;
611 }
612
613 /*
614  * Returns the request one like to get
615  */
616 comRequest* FastCommunication::getRequest(uint8_t status, uint32_t queue) {
617         uint8_t req = _currentRequest;
618
619         for (int i = 0; i < _nrOfRequest; i++) {
620                 if (_request[req].valid && _request[req].status == status
621                                 && _request[req].queue == queue) {
622                         _currentRequest = (req + 1) % _nrOfRequest;
623                         return &(_request[req]);
624                 }
625                 req = (req + 1) % _nrOfRequest;
626         }
627
628         return NULL;
629 }
630
631 /**
632  * True if no communication is necessary, false if there is active communication
633  */
634 bool FastCommunication::empty() {
635         // check if one fifo would like to send something to another SPE
636         for (int i = 0; i < _nrOfQueues; i++) {
637                 if (_fifos[i].type == this->out) {
638                         if (_fifos[i].iswfifo) {
639                                 if (_fifos[i].wfifo->used() > 0) 
640                                 {
641                                         return false;
642                                 }
643                         } else {
644                                 if (_fifos[i].fifo->used() > 0)
645                                 {
646                                         return false;
647                                 }
648                         }
649                 }
650         }
651
652         // are open sendings?
653         for (int i = 0; i < _nrOfRequest; i++) {
654                 if (_request[i].valid) {
655                         return false;
656                 }
657         }
658
659         return true;
660 }
661
662 void FastCommunication::sendMessage(uint32_t message, int32_t process) {
663         // Simple forward the message to the PPE
664         if (process <= -1) {
665                 spu_write_out_mbox(message);
666         }
667
668         // Forward message to the corresponding SPE
669         else {
670                 uint32_t tag_id;
671
672                 // reserve DMA tag ID
673                 if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
674                         printf("SPE: ERROR - can't reserve a tag ID\n");
675                         return;
676                 }
677
678                 //printf("SPE > OUT Message to process = %d, addr = %llx\n", process, _ea_base_all[process]);
679                 write_in_mbox(message, _ea_base_all[process], tag_id);
680                 mfc_tag_release(tag_id);
681         }
682 }
683
684 int FastCommunication::testMessage(int32_t process) {
685         //int32_t process = queueOnSPE[queue];
686
687         // Simple forward the message to the PPE
688         if (process <= -1) {
689                 return spu_stat_out_mbox();
690         }
691
692         // Forward message to the corresponding SPE
693         else {
694                 uint32_t tag_id;
695
696                 // reserve DMA tag ID
697                 if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
698                         printf("SPE: ERROR - can't reserve a tag ID\n");
699                         return 0;
700                 }
701
702                 // IMPORTANT: THIS IS NOT RACE CONDITION FREE!!!!
703                 int test = status_in_mbox(_ea_base_all[process], tag_id);
704                 mfc_tag_release(tag_id);
705                 return test;
706         }
707 }