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 DEFAULT_DEBUG_CHANNEL(shm
)
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 TRACE(shm
,"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 */
57 TRACE(shm
, "block was set up at 0x%08x, size=0x%04xKB, 1st usable=%02x\n",
58 (int )block
,size
/1024,first
);
61 /* shm_attach_block: attach existing shm block, setup selectors
62 * shm_id - id of the block to attach.
63 * proc_idx - if not -1, puts this data into local mapping
64 * map - localy mapped info about this block.
66 /* NOTE: there is no check if this block is already attached.
67 * Attaching the same block more than once - is possible
68 * In case of doubt use shm_locate_block.
70 struct shm_block
*shm_attach_block(int shm_id
, int proc_idx
,
71 struct local_shm_map
*map
)
73 struct shm_block
*block
;
75 struct local_shm_map
*this;
77 shmctl(shm_id
, IPC_STAT
, &ds
);
79 block
=(struct shm_block
*)shmat(shm_id
, NULL
, 0);
80 if (block
==NULL
|| block
== (struct shm_block
*) -1) return NULL
;
82 this=(struct local_shm_map
*)xmalloc(sizeof(*this));
89 this->proc_idx
=block
->proc_idx
;
91 this->proc_idx
=proc_idx
;
94 memcpy(map
, this, sizeof(map
));
95 map
->next
= NULL
; /* don't pass private info */
101 struct shm_block
*shm_create_block(int first
, int size
, int *shm_id
)
103 struct shm_block
*block
;
108 /* round up size to a multiple of SHM_MINBLOCK */
109 size
= (size
+SHM_MINBLOCK
-1) & ~(SHM_MINBLOCK
-1);
110 *shm_id
= shmget ( IPC_PRIVATE
, size
,0700);
113 block
=shm_attach_block(*shm_id
, curr_proc_idx
, NULL
);
115 shm_setup_block(block
, first
, size
);
121 ** Locate attached block. (return it, or NULL on failure)
122 ** shm_id is the block we look for.
123 ** *map - will get all the info related to this local map + proc_idx
125 ** *seg - will get the segment this block is attached to.
127 struct shm_block
*shm_locate_attached_block(int shm_id
,
128 struct local_shm_map
*map
)
130 struct local_shm_map
*curr
;
132 for (curr
= shm_map
; curr
!= NULL
; curr
= curr
->next
) {
133 if (curr
->shm_id
== shm_id
) {
135 memcpy(map
, curr
, sizeof(*curr
) );
136 map
->next
= NULL
; /* this is private info ! */
142 /* block not found ! */
146 /* shm_locate_block: see shm_attach_block.
147 In addition to shm_attach_block, make sure this
148 block is not already attached.
150 struct shm_block
*shm_locate_block(int shm_id
, struct local_shm_map
*map
)
153 struct shm_block
*ret
;
154 ret
= shm_locate_attached_block(shm_id
, map
);
157 /* block not found ! , try to attach */
158 return shm_attach_block(shm_id
, -1, map
);
161 static void forget_attached(int shmid
)
163 struct local_shm_map
*curr
, **point_to_curr
;
165 for (curr
= shm_map
, point_to_curr
= &shm_map
;
167 curr
= curr
->next
, point_to_curr
= &curr
->next
) {
168 if (curr
->shm_id
== shmid
) {
169 *point_to_curr
= curr
->next
;
175 /* delete chain of shm blocks (pointing to each other)
176 * Do it in reverse order. (This is what the recursion is for)
178 void shm_delete_chain(int *shmid
)
180 struct shm_block
*block
;
185 block
= shm_locate_block(*shmid
, NULL
);
186 forget_attached( *shmid
);
189 shm_delete_chain(&block
->next_shm_id
);
190 shmctl(*shmid
, IPC_RMID
, NULL
);
192 shmdt((char *)block
);
195 #endif /* CONFIG_IPC */