5
/* $Id: memlock.c,v 1.24.2.3 2007-08-29 17:32:32 manoj Exp $ */
13
#define INVALID_VAL -9999999
18
size_t armci_mem_offset=0;
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
27
int init_use_memlock_table=1;
28
int *armci_use_memlock_table=&init_use_memlock_table;
30
static int locked_slot=INVALID_VAL;
32
volatile double armci_dummy_work=0.;
33
void **memlock_table_array;
35
/* constants for cache line alignment */
39
#define ALIGN_ADDRESS(x) (char*)((((unsigned long)x) >> LOG_CALGN) << LOG_CALGN)
40
static memlock_t table[MAX_SLOTS];
43
/*\ simple locking scheme that ignores addresses
45
void armci_lockmem_(void *pstart, void *pend, int proc)
48
#if defined(CLUSTER) && !defined(SGIALTIX)
49
int lock = (proc-armci_clus_info[armci_clus_id(proc)].master)%NUM_LOCKS;
55
printf("%d: armci_lockmem_ proc=%d lock=%d\n",armci_me,proc,lock);
59
NATIVE_LOCK(lock,proc);
61
printf("%d: armci_lockmem_ done\n",armci_me);
66
void armci_unlockmem_(int proc)
69
#if defined(CLUSTER) && !defined(SGIALTIX)
70
int lock = (proc-armci_clus_info[armci_clus_id(proc)].master)%NUM_LOCKS;
75
printf("%d: armci_unlockmem_ proc=%d lock=%d\n",armci_me,proc,lock);
78
NATIVE_UNLOCK(lock,proc);
83
/*\ idle for a time proportional to factor
85
void armci_waitsome(int factor)
89
if(factor <= 1) armci_dummy_work =0.;
90
if(factor < 1) return;
92
armci_dummy_work = armci_dummy_work + 1./(double)i;
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
100
void armci_lockmem(void *start, void *end, int proc)
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;
113
if(! *armci_use_memlock_table){
114
/* if offset invalid, use dumb locking scheme ignoring addresses */
115
armci_lockmem_(start, end, proc);
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
123
if(armci_mem_offset){
124
start = armci_mem_offset + (char*)start;
125
end = armci_mem_offset + (char*)end;
131
printf("%d: calling armci_lockmem for %d range %p -%p\n",
132
armci_me, proc, start,end);
135
memlock_table = (memlock_t*)memlock_table_array[proc];
139
/* align address range on cache line boundary to avoid false sharing */
140
pstart = ALIGN_ADDRESS(start);
141
pend = CALGN -1 + ALIGN_ADDRESS(end);
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;
156
NATIVE_LOCK(lock,proc);
158
armci_get(memlock_table, table, sizeof(table), proc);
159
/* armci_copy(memlock_table, table, sizeof(table));*/
161
/* inspect the table */
162
conflict = 0; avail =-1;
163
for(slot = 0; slot < MAX_SLOTS; slot ++){
165
/* nonzero starting address means the slot is occupied */
166
if(table[slot].start == NULL){
168
/* remember a free slot to store address range */
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) ){
181
printf("%d: locking %ld-%ld (%d) conflict\n",
186
if(avail != -1 && !conflict) break;
188
NATIVE_UNLOCK(lock,proc);
189
armci_waitsome( ++turn );
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);
200
NATIVE_UNLOCK(lock,proc);
206
/*\ release lock to the memory area locked by previous call to armci_lockemem
208
void armci_unlockmem(int proc)
210
void *null[2] = {NULL,NULL};
211
memlock_t *memlock_table;
214
if(! *armci_use_memlock_table){
215
/* if offset invalid, use dumb locking scheme ignoring addresses */
216
armci_unlockmem_(proc);
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);
227
memlock_table = (memlock_t*)memlock_table_array[proc];
228
armci_put(null,&memlock_table[locked_slot].start,2*sizeof(void*),proc);
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
238
void armci_set_mem_offset(void *ptr)
240
extern size_t armci_mem_offset;
242
static int first_time=1;
243
volatile void *ref_ptr;
245
ARMCI_PR_DBG("enter",0);
246
/* do not care if memlock not used */
247
if(! *armci_use_memlock_table) return;
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);
255
armci_mem_offset =off;
258
printf("%d memlock offset=%ld ref=%p ptr=%p\n",armci_me,
259
(long)armci_mem_offset, ref_ptr, ptr); fflush(stdout);
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);