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

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src-portals/memlock.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
/* $Id: memlock.c,v 1.24.2.3 2007-08-29 17:32:32 manoj Exp $ */
 
6
#include "armcip.h"
 
7
#include "locks.h"
 
8
#include "copy.h"
 
9
#include "memlock.h"
 
10
#include <stdio.h>
 
11
 
 
12
#define DEBUG_ 0
 
13
#define INVALID_VAL -9999999
 
14
 
 
15
#ifdef DATA_SERVER
 
16
#  define CORRECT_PTR 
 
17
#endif
 
18
size_t armci_mem_offset=0;
 
19
 
 
20
/* We start by  using table: assign address of local variable set to 1
 
21
 * On shmem systems, this addres is overwritten by a shared memory location
 
22
 * when memlock array is allocated in armci_init 
 
23
 * Therefore, any process within shmem node can reset armci_use_memlock_table
 
24
 * to "not used" when offset changes. Since the variable is in shmem, everybody
 
25
 * on that SMP node will see the change and use the same locking functions
 
26
 */ 
 
27
int init_use_memlock_table=1;
 
28
int *armci_use_memlock_table=&init_use_memlock_table;
 
29
 
 
30
static int locked_slot=INVALID_VAL;
 
31
 
 
32
volatile double armci_dummy_work=0.;
 
33
void **memlock_table_array;
 
34
 
 
35
/* constants for cache line alignment */
 
36
#  define CALGN 64
 
37
#  define LOG_CALGN 6
 
38
 
 
39
#define ALIGN_ADDRESS(x) (char*)((((unsigned long)x) >> LOG_CALGN) << LOG_CALGN) 
 
40
static memlock_t table[MAX_SLOTS];
 
41
 
 
42
 
 
43
/*\ simple locking scheme that ignores addresses
 
44
\*/
 
45
void armci_lockmem_(void *pstart, void *pend, int proc)
 
46
{
 
47
 
 
48
#if defined(CLUSTER) && !defined(SGIALTIX)
 
49
    int lock = (proc-armci_clus_info[armci_clus_id(proc)].master)%NUM_LOCKS;
 
50
#else
 
51
    int lock = 0;
 
52
#endif
 
53
 
 
54
    if(DEBUG_){
 
55
      printf("%d: armci_lockmem_ proc=%d lock=%d\n",armci_me,proc,lock);
 
56
      fflush(stdout);
 
57
    }
 
58
 
 
59
    NATIVE_LOCK(lock,proc);
 
60
    if(DEBUG_){
 
61
      printf("%d: armci_lockmem_ done\n",armci_me);
 
62
      fflush(stdout);
 
63
    }
 
64
}
 
65
 
 
66
void armci_unlockmem_(int proc)
 
67
{
 
68
 
 
69
#if defined(CLUSTER) && !defined(SGIALTIX) 
 
70
    int lock = (proc-armci_clus_info[armci_clus_id(proc)].master)%NUM_LOCKS;
 
71
#else
 
72
    int lock = 0;
 
73
#endif
 
74
    if(DEBUG_){
 
75
      printf("%d: armci_unlockmem_ proc=%d lock=%d\n",armci_me,proc,lock);
 
76
      fflush(stdout);
 
77
    }
 
78
     NATIVE_UNLOCK(lock,proc);
 
79
}
 
80
 
 
81
 
 
82
 
 
83
/*\ idle for a time proportional to factor 
 
84
\*/
 
85
void armci_waitsome(int factor)
 
86
{
 
87
int i=factor*100000;
 
88
 
 
89
   if(factor <= 1) armci_dummy_work =0.;
 
90
   if(factor < 1) return;
 
91
   while(--i){
 
92
      armci_dummy_work = armci_dummy_work + 1./(double)i;  
 
93
   }
 
94
}
 
95
   
 
96
/*\ acquire exclusive LOCK to MEMORY area <pstart,pend> owned by process "proc"
 
97
 *   . only one area can be locked at a time by the calling process
 
98
 *   . must unlock it with armci_unlockmem
 
99
\*/
 
100
void armci_lockmem(void *start, void *end, int proc)
 
101
{
 
102
     register void* pstart, *pend;
 
103
     register  int slot, avail=0;
 
104
     int turn=0, conflict=0;
 
105
     memlock_t *memlock_table;
 
106
#if defined(CLUSTER) && !defined(SGIALTIX)
 
107
    int lock = (proc-armci_clus_info[armci_clus_id(proc)].master)%NUM_LOCKS;
 
108
#else
 
109
    int lock = 0;
 
110
#endif
 
111
 
 
112
#ifdef CORRECT_PTR
 
113
     if(! *armci_use_memlock_table){
 
114
       /* if offset invalid, use dumb locking scheme ignoring addresses */
 
115
       armci_lockmem_(start, end, proc); 
 
116
       return;
 
117
     }
 
118
 
 
119
#  ifndef SGIALTIX
 
120
     /* when processes are attached to a shmem region at different addresses,
 
121
      * addresses written to memlock table must be adjusted to the node master
 
122
      */
 
123
     if(armci_mem_offset){
 
124
        start = armci_mem_offset + (char*)start;
 
125
        end   = armci_mem_offset + (char*)end;
 
126
     }
 
127
#  endif
 
128
#endif
 
129
 
 
130
     if(DEBUG_){
 
131
       printf("%d: calling armci_lockmem for %d range %p -%p\n",
 
132
              armci_me, proc, start,end);
 
133
       fflush(stdout);
 
134
     }
 
135
     memlock_table = (memlock_t*)memlock_table_array[proc];
 
136
 
 
137
 
 
138
#ifdef ALIGN_ADDRESS
 
139
     /* align address range on cache line boundary to avoid false sharing */
 
140
     pstart = ALIGN_ADDRESS(start);
 
141
     pend = CALGN -1 + ALIGN_ADDRESS(end);
 
142
#else
 
143
     pstart=start;
 
144
     pend =end;
 
145
#endif
 
146
 
 
147
#ifdef CRAY_SHMEM
 
148
     { /* adjust according the remote process raw address */
 
149
        long bytes = (long) ((char*)pend-(char*)pstart);
 
150
        extern void* armci_shmalloc_remote_addr(void *ptr, int proc);
 
151
        pstart = armci_shmalloc_remote_addr(pstart, proc);
 
152
        pend   = (char*)pstart + bytes;
 
153
     }
 
154
#endif
 
155
     while(1){
 
156
        NATIVE_LOCK(lock,proc);
 
157
 
 
158
        armci_get(memlock_table, table, sizeof(table), proc);
 
159
/*        armci_copy(memlock_table, table, sizeof(table));*/
 
160
        
 
161
        /* inspect the table */
 
162
        conflict = 0; avail =-1;
 
163
        for(slot = 0; slot < MAX_SLOTS; slot ++){
 
164
 
 
165
            /* nonzero starting address means the slot is occupied */ 
 
166
            if(table[slot].start == NULL){
 
167
 
 
168
              /* remember a free slot to store address range */
 
169
              avail = slot;  
 
170
          
 
171
            }else{
 
172
              /*check for conflict: overlap between stored and current range*/
 
173
              if(  (pstart >= table[slot].start && pstart <= table[slot].end)
 
174
                 || (pend >= table[slot].start && pend <= table[slot].end) ){
 
175
 
 
176
                  conflict = 1;
 
177
                  break;
 
178
 
 
179
              }
 
180
              /*
 
181
              printf("%d: locking %ld-%ld (%d) conflict\n",
 
182
                  armci_me,  */
 
183
            }
 
184
       }
 
185
        
 
186
       if(avail != -1 && !conflict) break;
 
187
 
 
188
       NATIVE_UNLOCK(lock,proc);
 
189
       armci_waitsome( ++turn );
 
190
 
 
191
     }
 
192
 
 
193
     /* we got the memory lock: enter address into the table */
 
194
     table[avail].start = pstart;
 
195
     table[avail].end = pend;
 
196
     armci_put(table+avail,memlock_table+avail,sizeof(memlock_t),proc);
 
197
 
 
198
     FENCE_NODE(proc);
 
199
 
 
200
     NATIVE_UNLOCK(lock,proc);
 
201
     locked_slot = avail;
 
202
 
 
203
}
 
204
        
 
205
 
 
206
/*\ release lock to the memory area locked by previous call to armci_lockemem
 
207
\*/
 
208
void armci_unlockmem(int proc)
 
209
{
 
210
     void *null[2] = {NULL,NULL};
 
211
     memlock_t *memlock_table;
 
212
 
 
213
#ifdef CORRECT_PTR
 
214
     if(! *armci_use_memlock_table){
 
215
       /* if offset invalid, use dumb locking scheme ignoring addresses */
 
216
       armci_unlockmem_(proc);               
 
217
       return;
 
218
     }
 
219
#endif
 
220
 
 
221
#ifdef DEBUG
 
222
     if(locked_slot == INVALID_VAL) armci_die("armci_unlock: empty",0);
 
223
     if(locked_slot >= MAX_SLOTS || locked_slot <0) 
 
224
        armci_die("armci_unlock: corrupted slot?",locked_slot);
 
225
#endif
 
226
 
 
227
     memlock_table = (memlock_t*)memlock_table_array[proc];
 
228
     armci_put(null,&memlock_table[locked_slot].start,2*sizeof(void*),proc);
 
229
 
 
230
}
 
231
 
 
232
 
 
233
 
 
234
/*\ based on address for set by master, determine correction for
 
235
 *  memory addresses set in memlock table
 
236
 *  if the correction/offset ever changes stop using memlock table locking
 
237
\*/ 
 
238
void armci_set_mem_offset(void *ptr)
 
239
{
 
240
   extern size_t armci_mem_offset;
 
241
   size_t off;
 
242
   static int first_time=1;
 
243
   volatile void *ref_ptr;
 
244
 
 
245
    ARMCI_PR_DBG("enter",0);
 
246
   /* do not care if memlock not used */
 
247
   if(! *armci_use_memlock_table) return;
 
248
 
 
249
   if(!ptr) armci_die("armci_set_mem_offset : null ptr",0);
 
250
   ref_ptr = *(void**)ptr;
 
251
   off = (size_t)((char*)ref_ptr - (char*)ptr);
 
252
 
 
253
   if(first_time){
 
254
 
 
255
      armci_mem_offset =off;
 
256
      first_time =0;
 
257
      if(DEBUG_){
 
258
        printf("%d memlock offset=%ld ref=%p ptr=%p\n",armci_me,
 
259
                  (long)armci_mem_offset, ref_ptr, ptr); fflush(stdout);
 
260
      }
 
261
 
 
262
   }else{
 
263
      if(armci_mem_offset != off){
 
264
         *armci_use_memlock_table =0;
 
265
         fprintf(stderr, "%d: WARNING:armci_set_mem_offset: offset changed %ld to %ld\n",
 
266
                 armci_me, (long)armci_mem_offset, (long)off); fflush(stdout);
 
267
      }
 
268
   }
 
269
}