~ubuntu-branches/ubuntu/utopic/nwchem/utopic

« back to all changes in this revision

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