~ubuntu-branches/ubuntu/trusty/nwchem/trusty-proposed

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src/devices/dcmf/dcmf-0.3.0/armcix_lock.c

  • Committer: Package Import Robot
  • Author(s): Michael Banck, Daniel Leidert, Andreas Tille, Michael Banck
  • Date: 2013-07-04 12:14:55 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130704121455-5tvsx2qabor3nrui
Tags: 6.3-1
* New upstream release.
* Fixes anisotropic properties (Closes: #696361).
* New features include:
  + Multi-reference coupled cluster (MRCC) approaches
  + Hybrid DFT calculations with short-range HF 
  + New density-functionals including Minnesota (M08, M11) and HSE hybrid
    functionals
  + X-ray absorption spectroscopy (XAS) with TDDFT
  + Analytical gradients for the COSMO solvation model
  + Transition densities from TDDFT 
  + DFT+U and Electron-Transfer (ET) methods for plane wave calculations
  + Exploitation of space group symmetry in plane wave geometry optimizations
  + Local density of states (LDOS) collective variable added to Metadynamics
  + Various new XC functionals added for plane wave calculations, including
    hybrid and range-corrected ones
  + Electric field gradients with relativistic corrections 
  + Nudged Elastic Band optimization method
  + Updated basis sets and ECPs 

[ Daniel Leidert ]
* debian/watch: Fixed.

[ Andreas Tille ]
* debian/upstream: References

[ Michael Banck ]
* debian/upstream (Name): New field.
* debian/patches/02_makefile_flags.patch: Refreshed.
* debian/patches/06_statfs_kfreebsd.patch: Likewise.
* debian/patches/07_ga_target_force_linux.patch: Likewise.
* debian/patches/05_avoid_inline_assembler.patch: Removed, no longer needed.
* debian/patches/09_backported_6.1.1_fixes.patch: Likewise.
* debian/control (Build-Depends): Added gfortran-4.7 and gcc-4.7.
* debian/patches/10_force_gcc-4.7.patch: New patch, explicitly sets
  gfortran-4.7 and gcc-4.7, fixes test suite hang with gcc-4.8 (Closes:
  #701328, #713262).
* debian/testsuite: Added tests for COSMO analytical gradients and MRCC.
* debian/rules (MRCC_METHODS): New variable, required to enable MRCC methods.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if HAVE_CONFIG_H
 
2
#   include "config.h"
 
3
#endif
 
4
/* begin_generated_IBM_copyright_prolog                             */
 
5
/*                                                                  */
 
6
/* ---------------------------------------------------------------- */
 
7
/* (C)Copyright IBM Corp.  2007, 2008                               */
 
8
/* IBM BSD License                                                  */
 
9
/* ---------------------------------------------------------------- */
 
10
/*                                                                  */
 
11
/* end_generated_IBM_copyright_prolog                               */
 
12
/**
 
13
 * \file armci/src/armcix/dcmf/armcix_lock.c
 
14
 * \brief DCMF ARMCI Extension for lock operations.
 
15
 */
 
16
 
 
17
#include "armcix_impl.h"
 
18
 
 
19
typedef struct ARMCIX_DCMF_Lockwaiter_t
 
20
{
 
21
  unsigned   peer;
 
22
  void     * start;
 
23
  void     * end;
 
24
  unsigned * update;
 
25
}
 
26
ARMCIX_DCMF_Lockwaiter_t;
 
27
 
 
28
typedef struct ARMCIX_DCMF_Lockwaitq_t
 
29
{
 
30
  ARMCIX_DCMF_Lockwaiter_t * queue;
 
31
  unsigned                   size;
 
32
  unsigned                   head;
 
33
  unsigned                   tail;
 
34
}
 
35
ARMCIX_DCMF_Lockwaitq_t;
 
36
 
 
37
typedef enum
 
38
{
 
39
  ARMCIX_DCMF_Lock_Request,
 
40
  ARMCIX_DCMF_Lock_Ack,
 
41
  ARMCIX_DCMF_Lock_Release
 
42
}
 
43
ARMCIX_DCMF_Lockinfo_operation_t;
 
44
 
 
45
typedef struct ARMCIX_DCMF_Lockinfo_t
 
46
{
 
47
  ARMCIX_DCMF_Lockinfo_operation_t op;
 
48
  unsigned     * update;
 
49
  union
 
50
  {
 
51
    struct
 
52
    {
 
53
      void     * start;
 
54
      void     * end;
 
55
    } request;
 
56
    struct
 
57
    {
 
58
      unsigned   slot;
 
59
      unsigned   unused;
 
60
    } key;
 
61
  };
 
62
}
 
63
ARMCIX_DCMF_Lockinfo_t __attribute__ ((__aligned__ (16)));
 
64
 
 
65
/** Lock operation DCMF protocol global object. */
 
66
DCMF_Protocol_t         __lock_req_protocol;
 
67
DCMF_Protocol_t         __lock_ack_protocol;
 
68
 
 
69
/**
 
70
 * \brief Origin node active lock slots.
 
71
 */
 
72
#if (MAX_SLOTS > 256)
 
73
#error MAX_SLOTS must be less than or equal to 256
 
74
#endif
 
75
unsigned char              * __lock_slot;
 
76
 
 
77
/** Target node pending lock queue. */
 
78
ARMCIX_DCMF_Lockwaitq_t __lock_pending;
 
79
 
 
80
/**
 
81
 * \brief Acquire a lock on a memory address range.
 
82
 *
 
83
 * Inspects the memory lock table and, if there is an open slot and the
 
84
 * requested memory address range does not conflict with an existing lock,
 
85
 * updates the memory locak table with the lock information and returns
 
86
 * the slot of the acquired lock.
 
87
 *
 
88
 * \todo Can this be moved up to a more platform-neutral place?
 
89
 *
 
90
 * \param[in] local_memlock_table The memory lock table
 
91
 * \param[in] pstart              The start of the memory address range
 
92
 * \param[in] pend                The end of the memory address range
 
93
 *
 
94
 * \return    The memory lock table slot of the successfully acquired lock, 
 
95
 *            otherwise \c -1
 
96
 *
 
97
 * \see ARMCIX_release_lock
 
98
 */
 
99
int ARMCIX_aquire_lock (memlock_t * local_memlock_table, void * pstart, void * pend)
 
100
{
 
101
  int acquired_lock = -1;
 
102
 
 
103
  /* inspect the table */
 
104
  unsigned conflict = 0; 
 
105
  unsigned slot = 0;
 
106
  for(; slot < MAX_SLOTS; slot++)
 
107
    {
 
108
      /* nonzero starting address means the slot is occupied */ 
 
109
      if(local_memlock_table[slot].start == NULL)
 
110
        {
 
111
          /* remember a free slot to store address range */
 
112
          acquired_lock = slot;
 
113
        }
 
114
      else
 
115
        {
 
116
          /* check for conflict: overlap between stored and current range */
 
117
          if ( (pstart >= local_memlock_table[slot].start &&
 
118
                pstart <= local_memlock_table[slot].end) ||
 
119
               (pend >= local_memlock_table[slot].start &&
 
120
                pend <= local_memlock_table[slot].end) )
 
121
            {
 
122
              conflict = 1;
 
123
              break;
 
124
            }
 
125
        }
 
126
    }
 
127
 
 
128
  if (acquired_lock != -1 && !conflict)
 
129
    {
 
130
      /* acquired the memory lock: enter address into the table */
 
131
      local_memlock_table[acquired_lock].start = pstart;
 
132
      local_memlock_table[acquired_lock].end = pend;
 
133
    }
 
134
  else
 
135
    {
 
136
      acquired_lock = -1;
 
137
    }
 
138
 
 
139
  return acquired_lock;
 
140
}
 
141
 
 
142
/**
 
143
 * \brief Release a lock of the memory address range in the specified lock slot.
 
144
 *
 
145
 * Clears the memory address range in specified lock slot of the memory lock
 
146
 * table.
 
147
 *
 
148
 * \todo Can this be moved up to a more platform-neutral place?
 
149
 *
 
150
 * \param[in] local_memlock_table The memory lock table
 
151
 * \param[in] slot                The memory lock slot to release
 
152
 *
 
153
 * \see ARMCIX_aquire_lock
 
154
 */
 
155
void ARMCIX_release_lock (memlock_t * local_memlock_table, unsigned slot)
 
156
{
 
157
  local_memlock_table[slot].start = NULL;
 
158
  local_memlock_table[slot].end   = NULL;
 
159
}
 
160
 
 
161
/**
 
162
 * \brief Receive a lock control message.
 
163
 *
 
164
 * The lock message type is either a lock \e request, \e acknowledgement, 
 
165
 * or \e release.
 
166
 *
 
167
 * For a lock request message the local memlock table is inspected for an 
 
168
 * available lock slot.  If a slot is found a lock acknowledgement message
 
169
 * is immediately sent to the peer node. Otherwise, the lock request
 
170
 * information is saved in a pending queue.
 
171
 *
 
172
 * The lock acknowledgment message is sent from the target node when the
 
173
 * origin node has acquired a lock of a resource on the target node. The
 
174
 * update variable is unset which will end the polling advance operation
 
175
 * inside the blocking ARMCIX_Lockmem() function.
 
176
 *
 
177
 * The lock release message frees the specified slot and attempts to acquire
 
178
 * a lock for the first lock waiter in the pending queue. If the lock is 
 
179
 * aqcuired then a lock acknowledgement is sent to the waiter.
 
180
 *
 
181
 * \param[in] clientdata Registered clientdata, the armci connection array
 
182
 * \param[in] info       Lock control information
 
183
 * \param[in] peer       Rank of the node that sent this control message
 
184
 *
 
185
 * \see DCMF_RecvControl
 
186
 */
 
187
void ARMCIX_DCMF_RecvLockMessage (void                 * clientdata,
 
188
                                  const DCMF_Control_t * info,
 
189
                                  unsigned               peer)
 
190
{
 
191
  /* Get the lock information sent with this lock message                    */
 
192
  ARMCIX_DCMF_Lockinfo_t * lockinfo = (ARMCIX_DCMF_Lockinfo_t *) info;
 
193
 
 
194
  switch (lockinfo->op)
 
195
  {
 
196
    case ARMCIX_DCMF_Lock_Request:
 
197
      {
 
198
        unsigned queue_request = 1;
 
199
        if (__lock_pending.head == __lock_pending.tail)
 
200
        {
 
201
          /* There are no pending lock requests. Attempt to acquire the      */
 
202
          /* request lock.                                                   */
 
203
          int lock = ARMCIX_aquire_lock ((memlock_t *) clientdata, lockinfo->request.start, lockinfo->request.end);
 
204
          if (lock != -1)
 
205
          {
 
206
            /* The lock was acquired. Send a lock acknowledgement message to */
 
207
            /* the origin node with the slot of the aquired lock and the     */
 
208
            /* address of the update variable on the origin node.            */
 
209
            ARMCIX_DCMF_Lockinfo_t ack;
 
210
            ack.op             = ARMCIX_DCMF_Lock_Ack;
 
211
            ack.update         = lockinfo->update;
 
212
            ack.key.slot       = lock;
 
213
            ack.key.unused     = 0;
 
214
 
 
215
            DCMF_Control (&__lock_ack_protocol,
 
216
                          DCMF_SEQUENTIAL_CONSISTENCY,
 
217
                          peer,
 
218
                         (DCMF_Control_t *) &ack);
 
219
 
 
220
            queue_request = 0;
 
221
          }
 
222
        }
 
223
 
 
224
        if (queue_request)
 
225
        {
 
226
          /* There were pending lock requests, or the acquire lock attempt   */
 
227
          /* failed. Queue the lock request until another node releases a    */
 
228
          /* lock.                                                           */
 
229
          ARMCIX_DCMF_Lockwaiter_t * tail = &__lock_pending.queue[__lock_pending.tail];
 
230
          tail->peer   = peer;
 
231
          tail->start  = lockinfo->request.start;
 
232
          tail->end    = lockinfo->request.end;
 
233
          tail->update = lockinfo->update;
 
234
 
 
235
          /* Advance the tail index                                            */
 
236
          __lock_pending.tail = (__lock_pending.tail+1)%__lock_pending.size;
 
237
        }
 
238
      }
 
239
      break;
 
240
 
 
241
    case ARMCIX_DCMF_Lock_Ack:
 
242
 
 
243
      /* Save the lock slot until the lock is released.                      */
 
244
      __lock_slot[peer] = lockinfo->key.slot;
 
245
 
 
246
      /* Set the update variable to zero. This will break the polling loop   */
 
247
      /* in ARMCIX_Lockmem() and allow that function to return.              */
 
248
      *(lockinfo->update) = 0;
 
249
      break;
 
250
 
 
251
    case ARMCIX_DCMF_Lock_Release:
 
252
      {
 
253
        /* Release the lock in this slot.                                    */
 
254
        ARMCIX_release_lock ((memlock_t *) clientdata, lockinfo->key.slot);
 
255
 
 
256
        if (__lock_pending.head != __lock_pending.tail)
 
257
        {
 
258
          /* There is a pending lock request. Attempt to acquire the lock as */
 
259
          /* specified in the pending queue now that the previous lock has   */
 
260
          /* been released.                                                  */
 
261
          ARMCIX_DCMF_Lockwaiter_t * head = &__lock_pending.queue[__lock_pending.head];
 
262
          int lock = ARMCIX_aquire_lock ((memlock_t *) clientdata, head->start, head->end);
 
263
          if (lock != -1)
 
264
          {
 
265
            /* The aquire lock attempt was successful. Send a lock           */
 
266
            /* acknowledgement message to the origin node of the pending     */
 
267
            /* lock request with the slot of the aquired lock and the        */
 
268
            /* address of the update variable on the origin node.            */
 
269
            ARMCIX_DCMF_Lockinfo_t ack;
 
270
            ack.op             = ARMCIX_DCMF_Lock_Ack;
 
271
            ack.update         = head->update;
 
272
            ack.key.slot       = lock;
 
273
            ack.key.unused     = 0;
 
274
 
 
275
            DCMF_Control (&__lock_ack_protocol,
 
276
                          DCMF_SEQUENTIAL_CONSISTENCY,
 
277
                          head->peer,
 
278
                          (DCMF_Control_t *) &ack);
 
279
 
 
280
           /* Advance the head index (dequeue the pending lock request)      */
 
281
            __lock_pending.head = (__lock_pending.head+1)%__lock_pending.size;
 
282
          }
 
283
        }
 
284
      }
 
285
      break;
 
286
    default:
 
287
      /* Bad! Bad! */
 
288
      assert (0);
 
289
      break;
 
290
  }
 
291
}
 
292
 
 
293
 
 
294
/**
 
295
 * \brief DCMF ARMCI Extention receive short lock request callback
 
296
 *
 
297
 * \see ARMCIX_DCMF_RecvLockAck
 
298
 * \see DCMF_RecvSendShort
 
299
 */
 
300
void ARMCIX_DCMF_RecvLockRequest (void           * clientdata,
 
301
                                  const DCQuad   * msginfo,
 
302
                                  unsigned         count,
 
303
                                  unsigned         peer,
 
304
                                  const char     * src,
 
305
                                  unsigned         bytes)
 
306
{
 
307
  ARMCIX_DCMF_RecvLockMessage (clientdata, (const DCMF_Control_t *) msginfo, peer);
 
308
}
 
309
 
 
310
 
 
311
/**
 
312
 * \brief Initialize the ARMCI Extention lock resources.
 
313
 *
 
314
 * Register the DCMF Control protocol used to pass lock messages between nodes.
 
315
 * Allocate a lock pending queue for use when a lock request is received by
 
316
 * the receive callback function ARMCIX_DCMF_RecvLockMessage() and the resource
 
317
 * is currently allocated to another node.
 
318
 *
 
319
 * \param[in]  local_memlock_table memlock table
 
320
 *
 
321
 * \see ARMCIX_DCMF_Lockwaitq_t
 
322
 * \see ARMCIX_DCMF_Lockwaiter_t
 
323
 * \see ARMCIX_DCMF_RecvLockMessage
 
324
 * \see DCMF_Control_register
 
325
 */
 
326
void ARMCIX_init_memlock (memlock_t * local_memlock_table)
 
327
{
 
328
  DCMF_CriticalSection_enter (0);
 
329
 
 
330
  DCMF_Send_Configuration_t send_configuration = {
 
331
    DCMF_DEFAULT_SEND_PROTOCOL,
 
332
    DCMF_DEFAULT_NETWORK,
 
333
    ARMCIX_DCMF_RecvLockRequest,
 
334
    local_memlock_table,
 
335
    NULL,
 
336
    NULL
 
337
  };
 
338
  DCMF_Send_register (&__lock_req_protocol, &send_configuration);
 
339
 
 
340
  DCMF_Control_Configuration_t ctrl_configuration = {
 
341
    DCMF_DEFAULT_CONTROL_PROTOCOL,
 
342
    DCMF_DEFAULT_NETWORK,
 
343
    ARMCIX_DCMF_RecvLockMessage,
 
344
    local_memlock_table
 
345
  };
 
346
  DCMF_Control_register (&__lock_ack_protocol, &ctrl_configuration);
 
347
 
 
348
  unsigned msize = DCMF_Messager_size ();
 
349
  unsigned qsize = sizeof(ARMCIX_DCMF_Lockwaiter_t) * msize+1;
 
350
  __lock_pending.size = msize;
 
351
  __lock_pending.queue = (ARMCIX_DCMF_Lockwaiter_t *) malloc (qsize);
 
352
  __lock_pending.head = 0;
 
353
  __lock_pending.tail = 0;
 
354
 
 
355
  __lock_slot = (unsigned char *) malloc (sizeof(unsigned char) * msize);
 
356
  memset(__lock_slot, 0x00, sizeof(unsigned char) * msize);
 
357
 
 
358
  DCMF_CriticalSection_exit (0);
 
359
}
 
360
 
 
361
/**
 
362
 * \brief ARMCI Extension blocking memory lock operation.
 
363
 *
 
364
 * Send a lock request to the remote node and block until the lock has been
 
365
 * acquired on the remote node.
 
366
 *
 
367
 * \param[in] pstart The start virtual address of the range of memory to lock.
 
368
 * \param[in] pend   The end virtual address of the range of memory to lock.
 
369
 * \param[in] proc   Remote process(or) ID
 
370
 *
 
371
 * \see ARMCIX_DCMF_Lockinfo_t
 
372
 * \see ARMCIX_DCMF_RecvLockMessage
 
373
 * \see DCMF_Control
 
374
 */
 
375
void ARMCIX_Lockmem (void * pstart, void * pend, int proc)
 
376
{
 
377
  DCMF_CriticalSection_enter (0);
 
378
 
 
379
  volatile unsigned active = 1;
 
380
 
 
381
  ARMCIX_DCMF_Lockinfo_t info;
 
382
  info.op             = ARMCIX_DCMF_Lock_Request;
 
383
  info.update         = (unsigned *)&active;
 
384
  info.request.start  = pstart;
 
385
  info.request.end    = pend;
 
386
 
 
387
  DCMF_Request_t request;
 
388
  DCMF_Send ( &__lock_req_protocol,
 
389
              &request,
 
390
              (DCMF_Callback_t) { NULL, NULL },
 
391
              DCMF_SEQUENTIAL_CONSISTENCY,
 
392
              proc,
 
393
              0,
 
394
              NULL,
 
395
              (DCQuad *) &info,
 
396
              sizeof(ARMCIX_DCMF_Lockinfo_t)/sizeof(DCQuad));
 
397
 
 
398
  while (active) DCMF_Messager_advance ();
 
399
 
 
400
  DCMF_CriticalSection_exit  (0);
 
401
}
 
402
 
 
403
 
 
404
/**
 
405
 * \brief ARMCI Extension release memory lock operation.
 
406
 *
 
407
 * Send a lock release message to the remote node. This is a \e fire-and-forget
 
408
 * operation because the node does not block for an acknowledgement that the
 
409
 * lock release was successful.
 
410
 *
 
411
 * \param[in] proc   Remote process(or) ID
 
412
 *
 
413
 * \see ARMCIX_DCMF_Lockinfo_t
 
414
 * \see ARMCIX_DCMF_RecvLockMessage
 
415
 * \see DCMF_Control
 
416
 */
 
417
void ARMCIX_Unlockmem (int proc)
 
418
{
 
419
  DCMF_CriticalSection_enter (0);
 
420
 
 
421
  ARMCIX_DCMF_Lockinfo_t info;
 
422
  info.op              = ARMCIX_DCMF_Lock_Release;
 
423
  info.key.slot        = (unsigned) __lock_slot[proc];
 
424
  info.key.unused      = 0;
 
425
 
 
426
  DCMF_Request_t request;
 
427
  volatile unsigned active = 1;
 
428
  DCMF_Send ( &__lock_req_protocol,
 
429
              &request,
 
430
              (DCMF_Callback_t) { ARMCIX_DCMF_cb_decrement, (void *)&active },
 
431
              DCMF_SEQUENTIAL_CONSISTENCY,
 
432
              proc,
 
433
              0,
 
434
              NULL,
 
435
              (DCQuad *) &info,
 
436
              sizeof(ARMCIX_DCMF_Lockinfo_t)/sizeof(DCQuad));
 
437
 
 
438
  while (active) DCMF_Messager_advance ();
 
439
 
 
440
  DCMF_CriticalSection_exit  (0);
 
441
}