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>
22 #include "selectors.h"
23 #include "shm_fragment.h"
24 #include "shm_block.h"
25 #include "shm_semaph.h"
29 /* How each shmid is maped to local pointer */
30 /* Only attached shm blocks are in this construct */
31 struct local_shm_map
*shm_map
=NULL
;
33 /* setup a new shm block (construct a shm block object).
34 * block: The pointer to the memory block (local mapping)
35 * first: The first data byte (excluding header stuff),
36 * if 0 (zero) Use the default.
37 * size: The size of the memory block.
39 void shm_setup_block(struct shm_block
*block
, int first
, int size
)
41 dprintf_shm(stddeb
,"Setting up shm block at 0x%08x\n",(int )block
);
42 /* setup block internal data structure */
45 /* round up - so everything starts on cache line boundary
46 * (assume cache line=32 bytes, may be bigger/smaller for
47 * different processors and different L2 caches .)
49 first
=(first
+0x1f) & ~0x1f;
51 block
->free
=size
-first
;
52 block
->next_shm_id
=-1; /* IPC shm ID (for initial linking) */
53 block
->proc_idx
= curr_proc_idx
;
54 /* block->size is initialized in shm_FragmentInit */
55 shm_FragmentInit(block
, first
, size
); /* first item in the free list */
58 "block was set up at 0x%08x, size=0x%04xKB, 1st usable=%02x\n",
59 (int )block
,size
/1024,first
);
62 /* shm_attach_block: attach existing shm block, setup selectors
63 * shm_id - id of the block to attach.
64 * proc_idx - if not -1, puts this data into local mapping
65 * map - localy mapped info about this block.
67 /* NOTE: there is no check if this block is already attached.
68 * Attaching the same block more than once - is possible
69 * In case of doubt use shm_locate_block.
71 struct shm_block
*shm_attach_block(int shm_id
, int proc_idx
,
72 struct local_shm_map
*map
)
74 struct shm_block
*block
;
76 struct local_shm_map
*this;
78 shmctl(shm_id
, IPC_STAT
, &ds
);
80 block
=(struct shm_block
*)shmat(shm_id
, NULL
, 0);
81 if (block
==NULL
|| block
== (struct shm_block
*) -1) return NULL
;
83 this=(struct local_shm_map
*)xmalloc(sizeof(*this));
90 this->proc_idx
=block
->proc_idx
;
92 this->proc_idx
=proc_idx
;
95 memcpy(map
, this, sizeof(map
));
96 map
->next
= NULL
; /* don't pass private info */
102 struct shm_block
*shm_create_block(int first
, int size
, int *shm_id
)
104 struct shm_block
*block
;
109 /* round up size to a multiple of SHM_MINBLOCK */
110 size
= (size
+SHM_MINBLOCK
-1) & ~(SHM_MINBLOCK
-1);
111 *shm_id
= shmget ( IPC_PRIVATE
, size
,0700);
114 block
=shm_attach_block(*shm_id
, curr_proc_idx
, NULL
);
116 shm_setup_block(block
, first
, size
);
122 ** Locate attached block. (return it, or NULL on failure)
123 ** shm_id is the block we look for.
124 ** *map - will get all the info related to this local map + proc_idx
126 ** *seg - will get the segment this block is attached to.
128 struct shm_block
*shm_locate_attached_block(int shm_id
,
129 struct local_shm_map
*map
)
131 struct local_shm_map
*curr
;
133 for (curr
= shm_map
; curr
!= NULL
; curr
= curr
->next
) {
134 if (curr
->shm_id
== shm_id
) {
136 memcpy(map
, curr
, sizeof(*curr
) );
137 map
->next
= NULL
; /* this is private info ! */
143 /* block not found ! */
147 /* shm_locate_block: see shm_attach_block.
148 In addition to shm_attach_block, make sure this
149 block is not already attached.
151 struct shm_block
*shm_locate_block(int shm_id
, struct local_shm_map
*map
)
154 struct shm_block
*ret
;
155 ret
= shm_locate_attached_block(shm_id
, map
);
158 /* block not found ! , try to attach */
159 return shm_attach_block(shm_id
, -1, map
);
162 static void forget_attached(int shmid
)
164 struct local_shm_map
*curr
, **point_to_curr
;
166 for (curr
= shm_map
, point_to_curr
= &shm_map
;
168 curr
= curr
->next
, point_to_curr
= &curr
->next
) {
169 if (curr
->shm_id
== shmid
) {
170 *point_to_curr
= curr
->next
;
176 /* delete chain of shm blocks (pointing to each other)
177 * Do it in reverse order. (This is what the recursion is for)
179 void shm_delete_chain(int *shmid
)
181 struct shm_block
*block
;
186 block
= shm_locate_block(*shmid
, NULL
);
187 forget_attached( *shmid
);
190 shm_delete_chain(&block
->next_shm_id
);
191 shmctl(*shmid
, IPC_RMID
, NULL
);
193 shmdt((char *)block
);
196 #endif /* CONFIG_IPC */