1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
7 * Purpose: Treat a shared memory block.
8 ***************************************************************************
12 #define inline __inline__
13 #include <sys/types.h>
20 #include "selectors.h"
21 #include "shm_fragment.h"
22 #include "shm_block.h"
23 #include "shm_semaph.h"
27 /* How each shmid is maped to local pointer */
28 /* Only attached shm blocks are in this construct */
29 struct local_shm_map
*shm_map
=NULL
;
31 /* setup a new shm block (construct a shm block object).
32 * block: The pointer to the memory block (local mapping)
33 * first: The first data byte (excluding header stuff),
34 * if 0 (zero) Use the default.
35 * size: The size of the memory block.
37 void shm_setup_block(struct shm_block
*block
, int first
, int size
)
39 TRACE(shm
,"Setting up shm block at 0x%08x\n",(int )block
);
40 /* setup block internal data structure */
43 /* round up - so everything starts on cache line boundary
44 * (assume cache line=32 bytes, may be bigger/smaller for
45 * different processors and different L2 caches .)
47 first
=(first
+0x1f) & ~0x1f;
49 block
->free
=size
-first
;
50 block
->next_shm_id
=-1; /* IPC shm ID (for initial linking) */
51 block
->proc_idx
= curr_proc_idx
;
52 /* block->size is initialized in shm_FragmentInit */
53 shm_FragmentInit(block
, first
, size
); /* first item in the free list */
55 TRACE(shm
, "block was set up at 0x%08x, size=0x%04xKB, 1st usable=%02x\n",
56 (int )block
,size
/1024,first
);
59 /* shm_attach_block: attach existing shm block, setup selectors
60 * shm_id - id of the block to attach.
61 * proc_idx - if not -1, puts this data into local mapping
62 * map - localy mapped info about this block.
64 /* NOTE: there is no check if this block is already attached.
65 * Attaching the same block more than once - is possible
66 * In case of doubt use shm_locate_block.
68 struct shm_block
*shm_attach_block(int shm_id
, int proc_idx
,
69 struct local_shm_map
*map
)
71 struct shm_block
*block
;
73 struct local_shm_map
*this;
75 shmctl(shm_id
, IPC_STAT
, &ds
);
77 block
=(struct shm_block
*)shmat(shm_id
, NULL
, 0);
78 if (block
==NULL
|| block
== (struct shm_block
*) -1) return NULL
;
80 this=(struct local_shm_map
*)xmalloc(sizeof(*this));
87 this->proc_idx
=block
->proc_idx
;
89 this->proc_idx
=proc_idx
;
92 memcpy(map
, this, sizeof(map
));
93 map
->next
= NULL
; /* don't pass private info */
99 struct shm_block
*shm_create_block(int first
, int size
, int *shm_id
)
101 struct shm_block
*block
;
106 /* round up size to a multiple of SHM_MINBLOCK */
107 size
= (size
+SHM_MINBLOCK
-1) & ~(SHM_MINBLOCK
-1);
108 *shm_id
= shmget ( IPC_PRIVATE
, size
,0700);
111 block
=shm_attach_block(*shm_id
, curr_proc_idx
, NULL
);
113 shm_setup_block(block
, first
, size
);
119 ** Locate attached block. (return it, or NULL on failure)
120 ** shm_id is the block we look for.
121 ** *map - will get all the info related to this local map + proc_idx
123 ** *seg - will get the segment this block is attached to.
125 struct shm_block
*shm_locate_attached_block(int shm_id
,
126 struct local_shm_map
*map
)
128 struct local_shm_map
*curr
;
130 for (curr
= shm_map
; curr
!= NULL
; curr
= curr
->next
) {
131 if (curr
->shm_id
== shm_id
) {
133 memcpy(map
, curr
, sizeof(*curr
) );
134 map
->next
= NULL
; /* this is private info ! */
140 /* block not found ! */
144 /* shm_locate_block: see shm_attach_block.
145 In addition to shm_attach_block, make sure this
146 block is not already attached.
148 struct shm_block
*shm_locate_block(int shm_id
, struct local_shm_map
*map
)
151 struct shm_block
*ret
;
152 ret
= shm_locate_attached_block(shm_id
, map
);
155 /* block not found ! , try to attach */
156 return shm_attach_block(shm_id
, -1, map
);
159 static void forget_attached(int shmid
)
161 struct local_shm_map
*curr
, **point_to_curr
;
163 for (curr
= shm_map
, point_to_curr
= &shm_map
;
165 curr
= curr
->next
, point_to_curr
= &curr
->next
) {
166 if (curr
->shm_id
== shmid
) {
167 *point_to_curr
= curr
->next
;
173 /* delete chain of shm blocks (pointing to each other)
174 * Do it in reverse order. (This is what the recursion is for)
176 void shm_delete_chain(int *shmid
)
178 struct shm_block
*block
;
183 block
= shm_locate_block(*shmid
, NULL
);
184 forget_attached( *shmid
);
187 shm_delete_chain(&block
->next_shm_id
);
188 shmctl(*shmid
, IPC_RMID
, NULL
);
190 shmdt((char *)block
);
193 #endif /* CONFIG_IPC */