1 /* $Id$
2 
3 Copyright (C) 2013  The PARI group.
4 
5 This file is part of the PARI/GP package.
6 
7 PARI/GP is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 2 of the License, or (at your option) any later
10 version. It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY WHATSOEVER.
12 
13 Check the License for details. You should have received a copy of it, along
14 with the package; see the file 'COPYING'. If not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
16 #include "pari.h"
17 #include "paripriv.h"
18 #include "mt.h"
19 
20 static GEN
mtsingle_queue_get(struct mt_state * mt,long * workid,long * pending)21 mtsingle_queue_get(struct mt_state *mt, long *workid, long *pending)
22 {
23   GEN done = mt->pending;
24   if (workid) *workid = mt->workid;
25   mt->pending = NULL; *pending = 0;
26   return done;
27 }
28 
29 static int single_is_thread = 0;
30 static long single_trace_level = 0;
31 
32 static void
mtsingle_queue_submit(struct mt_state * mt,long workid,GEN work)33 mtsingle_queue_submit(struct mt_state *mt, long workid, GEN work)
34 {
35   single_is_thread = 1;
36   mt->pending = work? closure_callgenvec(mt->worker, work): NULL;
37   single_is_thread = 0;
38   mt->workid = workid;
39 }
40 
41 static void
mtsingle_queue_end(void)42 mtsingle_queue_end(void) {  }
43 
44 int
mtsingle_is_thread(void)45 mtsingle_is_thread(void) { return single_is_thread; }
46 
47 void
mtsingle_err_recover(long er)48 mtsingle_err_recover(long er)
49 {
50   (void) er;
51   if (single_is_thread)
52   {
53     evalstate_set_trace(single_trace_level);
54     single_is_thread = 0;
55   }
56 }
57 
58 void
mtsingle_queue_start(struct pari_mt * pt,GEN worker)59 mtsingle_queue_start(struct pari_mt *pt, GEN worker)
60 {
61   pt->get = mtsingle_queue_get;
62   pt->submit = mtsingle_queue_submit;
63   pt->end = mtsingle_queue_end;
64   pt->mt.worker = worker;
65   pt->mt.pending = NULL;
66   single_trace_level = evalstate_get_trace();
67 }
68 
69 void
mt_queue_end(struct pari_mt * pt)70 mt_queue_end(struct pari_mt *pt) { pt->end(); }
71 
72 void
mt_queue_submit(struct pari_mt * pt,long workid,GEN work)73 mt_queue_submit(struct pari_mt *pt, long workid, GEN work)
74 { pt->submit(&pt->mt, workid, work); }
75 
76 GEN
mt_queue_get(struct pari_mt * pt,long * workid,long * pending)77 mt_queue_get(struct pari_mt *pt, long *workid, long *pending)
78 { return pt->get(&pt->mt, workid, pending); }
79 
80 void
mt_queue_start(struct pari_mt * pt,GEN worker)81 mt_queue_start(struct pari_mt *pt, GEN worker)
82 { return mt_queue_start_lim(pt, worker, 0); }
83 
84 void
mtstate_save(struct pari_mtstate * mt)85 mtstate_save(struct pari_mtstate *mt)
86 {
87   mt->is_thread = single_is_thread;
88   mt->trace_level = single_trace_level;
89   mt->pending_threads = mt_is_parallel();
90 }
91 
92 void
mtstate_restore(struct pari_mtstate * mt)93 mtstate_restore(struct pari_mtstate *mt)
94 {
95   single_is_thread = mt->is_thread;
96   single_trace_level = mt->trace_level;
97   if (!mt->pending_threads && mt_is_parallel())
98     mt_queue_reset();
99 }
100 
101 void
mtstate_reset(void)102 mtstate_reset(void)
103 {
104   single_is_thread = 0;
105   single_trace_level = 0;
106   if (mt_is_parallel())
107     mt_queue_reset();
108 }
109