OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libgomp/] [task.c] - Blame information for rev 847

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 273 jeremybenn
/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
2
   Contributed by Richard Henderson <rth@redhat.com>.
3
 
4
   This file is part of the GNU OpenMP Library (libgomp).
5
 
6
   Libgomp is free software; you can redistribute it and/or modify it
7
   under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
 
11
   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
   more details.
15
 
16
   Under Section 7 of GPL version 3, you are granted additional
17
   permissions described in the GCC Runtime Library Exception, version
18
   3.1, as published by the Free Software Foundation.
19
 
20
   You should have received a copy of the GNU General Public License and
21
   a copy of the GCC Runtime Library Exception along with this program;
22
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
   <http://www.gnu.org/licenses/>.  */
24
 
25
/* This file handles the maintainence of tasks in response to task
26
   creation and termination.  */
27
 
28
#include "libgomp.h"
29
#include <stdlib.h>
30
#include <string.h>
31
 
32
 
33
/* Create a new task data structure.  */
34
 
35
void
36
gomp_init_task (struct gomp_task *task, struct gomp_task *parent_task,
37
                struct gomp_task_icv *prev_icv)
38
{
39
  task->parent = parent_task;
40
  task->icv = *prev_icv;
41
  task->kind = GOMP_TASK_IMPLICIT;
42
  task->in_taskwait = false;
43
  task->in_tied_task = false;
44
  task->children = NULL;
45
  gomp_sem_init (&task->taskwait_sem, 0);
46
}
47
 
48
/* Clean up a task, after completing it.  */
49
 
50
void
51
gomp_end_task (void)
52
{
53
  struct gomp_thread *thr = gomp_thread ();
54
  struct gomp_task *task = thr->task;
55
 
56
  gomp_finish_task (task);
57
  thr->task = task->parent;
58
}
59
 
60
static inline void
61
gomp_clear_parent (struct gomp_task *children)
62
{
63
  struct gomp_task *task = children;
64
 
65
  if (task)
66
    do
67
      {
68
        task->parent = NULL;
69
        task = task->next_child;
70
      }
71
    while (task != children);
72
}
73
 
74
/* Called when encountering an explicit task directive.  If IF_CLAUSE is
75
   false, then we must not delay in executing the task.  If UNTIED is true,
76
   then the task may be executed by any member of the team.  */
77
 
78
void
79
GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
80
           long arg_size, long arg_align, bool if_clause,
81
           unsigned flags __attribute__((unused)))
82
{
83
  struct gomp_thread *thr = gomp_thread ();
84
  struct gomp_team *team = thr->ts.team;
85
 
86
#ifdef HAVE_BROKEN_POSIX_SEMAPHORES
87
  /* If pthread_mutex_* is used for omp_*lock*, then each task must be
88
     tied to one thread all the time.  This means UNTIED tasks must be
89
     tied and if CPYFN is non-NULL IF(0) must be forced, as CPYFN
90
     might be running on different thread than FN.  */
91
  if (cpyfn)
92
    if_clause = false;
93
  if (flags & 1)
94
    flags &= ~1;
95
#endif
96
 
97
  if (!if_clause || team == NULL
98
      || team->task_count > 64 * team->nthreads)
99
    {
100
      struct gomp_task task;
101
 
102
      gomp_init_task (&task, thr->task, gomp_icv (false));
103
      task.kind = GOMP_TASK_IFFALSE;
104
      if (thr->task)
105
        task.in_tied_task = thr->task->in_tied_task;
106
      thr->task = &task;
107
      if (__builtin_expect (cpyfn != NULL, 0))
108
        {
109
          char buf[arg_size + arg_align - 1];
110
          char *arg = (char *) (((uintptr_t) buf + arg_align - 1)
111
                                & ~(uintptr_t) (arg_align - 1));
112
          cpyfn (arg, data);
113
          fn (arg);
114
        }
115
      else
116
        fn (data);
117
      if (task.children)
118
        {
119
          gomp_mutex_lock (&team->task_lock);
120
          gomp_clear_parent (task.children);
121
          gomp_mutex_unlock (&team->task_lock);
122
        }
123
      gomp_end_task ();
124
    }
125
  else
126
    {
127
      struct gomp_task *task;
128
      struct gomp_task *parent = thr->task;
129
      char *arg;
130
      bool do_wake;
131
 
132
      task = gomp_malloc (sizeof (*task) + arg_size + arg_align - 1);
133
      arg = (char *) (((uintptr_t) (task + 1) + arg_align - 1)
134
                      & ~(uintptr_t) (arg_align - 1));
135
      gomp_init_task (task, parent, gomp_icv (false));
136
      task->kind = GOMP_TASK_IFFALSE;
137
      task->in_tied_task = parent->in_tied_task;
138
      thr->task = task;
139
      if (cpyfn)
140
        cpyfn (arg, data);
141
      else
142
        memcpy (arg, data, arg_size);
143
      thr->task = parent;
144
      task->kind = GOMP_TASK_WAITING;
145
      task->fn = fn;
146
      task->fn_data = arg;
147
      task->in_tied_task = true;
148
      gomp_mutex_lock (&team->task_lock);
149
      if (parent->children)
150
        {
151
          task->next_child = parent->children;
152
          task->prev_child = parent->children->prev_child;
153
          task->next_child->prev_child = task;
154
          task->prev_child->next_child = task;
155
        }
156
      else
157
        {
158
          task->next_child = task;
159
          task->prev_child = task;
160
        }
161
      parent->children = task;
162
      if (team->task_queue)
163
        {
164
          task->next_queue = team->task_queue;
165
          task->prev_queue = team->task_queue->prev_queue;
166
          task->next_queue->prev_queue = task;
167
          task->prev_queue->next_queue = task;
168
        }
169
      else
170
        {
171
          task->next_queue = task;
172
          task->prev_queue = task;
173
          team->task_queue = task;
174
        }
175
      ++team->task_count;
176
      gomp_team_barrier_set_task_pending (&team->barrier);
177
      do_wake = team->task_running_count + !parent->in_tied_task
178
                < team->nthreads;
179
      gomp_mutex_unlock (&team->task_lock);
180
      if (do_wake)
181
        gomp_team_barrier_wake (&team->barrier, 1);
182
    }
183
}
184
 
185
void
186
gomp_barrier_handle_tasks (gomp_barrier_state_t state)
187
{
188
  struct gomp_thread *thr = gomp_thread ();
189
  struct gomp_team *team = thr->ts.team;
190
  struct gomp_task *task = thr->task;
191
  struct gomp_task *child_task = NULL;
192
  struct gomp_task *to_free = NULL;
193
 
194
  gomp_mutex_lock (&team->task_lock);
195
  if (gomp_barrier_last_thread (state))
196
    {
197
      if (team->task_count == 0)
198
        {
199
          gomp_team_barrier_done (&team->barrier, state);
200
          gomp_mutex_unlock (&team->task_lock);
201
          gomp_team_barrier_wake (&team->barrier, 0);
202
          return;
203
        }
204
      gomp_team_barrier_set_waiting_for_tasks (&team->barrier);
205
    }
206
 
207
  while (1)
208
    {
209
      if (team->task_queue != NULL)
210
        {
211
          struct gomp_task *parent;
212
 
213
          child_task = team->task_queue;
214
          parent = child_task->parent;
215
          if (parent && parent->children == child_task)
216
            parent->children = child_task->next_child;
217
          child_task->prev_queue->next_queue = child_task->next_queue;
218
          child_task->next_queue->prev_queue = child_task->prev_queue;
219
          if (child_task->next_queue != child_task)
220
            team->task_queue = child_task->next_queue;
221
          else
222
            team->task_queue = NULL;
223
          child_task->kind = GOMP_TASK_TIED;
224
          team->task_running_count++;
225
          if (team->task_count == team->task_running_count)
226
            gomp_team_barrier_clear_task_pending (&team->barrier);
227
        }
228
      gomp_mutex_unlock (&team->task_lock);
229
      if (to_free)
230
        {
231
          gomp_finish_task (to_free);
232
          free (to_free);
233
          to_free = NULL;
234
        }
235
      if (child_task)
236
        {
237
          thr->task = child_task;
238
          child_task->fn (child_task->fn_data);
239
          thr->task = task;
240
        }
241
      else
242
        return;
243
      gomp_mutex_lock (&team->task_lock);
244
      if (child_task)
245
        {
246
          struct gomp_task *parent = child_task->parent;
247
          if (parent)
248
            {
249
              child_task->prev_child->next_child = child_task->next_child;
250
              child_task->next_child->prev_child = child_task->prev_child;
251
              if (parent->children == child_task)
252
                {
253
                  if (child_task->next_child != child_task)
254
                    parent->children = child_task->next_child;
255
                  else
256
                    {
257
                      parent->children = NULL;
258
                      if (parent->in_taskwait)
259
                        gomp_sem_post (&parent->taskwait_sem);
260
                    }
261
                }
262
            }
263
          gomp_clear_parent (child_task->children);
264
          to_free = child_task;
265
          child_task = NULL;
266
          team->task_running_count--;
267
          if (--team->task_count == 0
268
              && gomp_team_barrier_waiting_for_tasks (&team->barrier))
269
            {
270
              gomp_team_barrier_done (&team->barrier, state);
271
              gomp_mutex_unlock (&team->task_lock);
272
              gomp_team_barrier_wake (&team->barrier, 0);
273
            }
274
        }
275
    }
276
}
277
 
278
/* Called when encountering a taskwait directive.  */
279
 
280
void
281
GOMP_taskwait (void)
282
{
283
  struct gomp_thread *thr = gomp_thread ();
284
  struct gomp_team *team = thr->ts.team;
285
  struct gomp_task *task = thr->task;
286
  struct gomp_task *child_task = NULL;
287
  struct gomp_task *to_free = NULL;
288
 
289
  if (task == NULL || task->children == NULL)
290
    return;
291
  gomp_mutex_lock (&team->task_lock);
292
  while (1)
293
    {
294
      if (task->children == NULL)
295
        {
296
          gomp_mutex_unlock (&team->task_lock);
297
          if (to_free)
298
            {
299
              gomp_finish_task (to_free);
300
              free (to_free);
301
            }
302
          return;
303
        }
304
      if (task->children->kind == GOMP_TASK_WAITING)
305
        {
306
          child_task = task->children;
307
          task->children = child_task->next_child;
308
          child_task->prev_queue->next_queue = child_task->next_queue;
309
          child_task->next_queue->prev_queue = child_task->prev_queue;
310
          if (team->task_queue == child_task)
311
            {
312
              if (child_task->next_queue != child_task)
313
                team->task_queue = child_task->next_queue;
314
              else
315
                team->task_queue = NULL;
316
            }
317
          child_task->kind = GOMP_TASK_TIED;
318
          team->task_running_count++;
319
          if (team->task_count == team->task_running_count)
320
            gomp_team_barrier_clear_task_pending (&team->barrier);
321
        }
322
      else
323
        /* All tasks we are waiting for are already running
324
           in other threads.  Wait for them.  */
325
        task->in_taskwait = true;
326
      gomp_mutex_unlock (&team->task_lock);
327
      if (to_free)
328
        {
329
          gomp_finish_task (to_free);
330
          free (to_free);
331
          to_free = NULL;
332
        }
333
      if (child_task)
334
        {
335
          thr->task = child_task;
336
          child_task->fn (child_task->fn_data);
337
          thr->task = task;
338
        }
339
      else
340
        {
341
          gomp_sem_wait (&task->taskwait_sem);
342
          task->in_taskwait = false;
343
          return;
344
        }
345
      gomp_mutex_lock (&team->task_lock);
346
      if (child_task)
347
        {
348
          child_task->prev_child->next_child = child_task->next_child;
349
          child_task->next_child->prev_child = child_task->prev_child;
350
          if (task->children == child_task)
351
            {
352
              if (child_task->next_child != child_task)
353
                task->children = child_task->next_child;
354
              else
355
                task->children = NULL;
356
            }
357
          gomp_clear_parent (child_task->children);
358
          to_free = child_task;
359
          child_task = NULL;
360
          team->task_count--;
361
          team->task_running_count--;
362
        }
363
    }
364
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.