1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
32:
33: #include <rthw.h>
34: #include <rtthread.h>
35:
36: #ifdef RT_USING_MEMPOOL
37:
38: #ifdef RT_USING_HOOK
39: static void (*rt_mp_alloc_hook)(struct rt_mempool *mp, void *block);
40: static void (*rt_mp_free_hook)(struct rt_mempool *mp, void *block);
41:
42: 43: 44:
45:
46:
47:
48: 49: 50: 51: 52: 53:
54: void rt_mp_alloc_sethook(void (*hook)(struct rt_mempool *mp, void *block))
55: {
56: rt_mp_alloc_hook = hook;
57: }
58:
59: 60: 61: 62: 63: 64:
65: void rt_mp_free_sethook(void (*hook)(struct rt_mempool *mp, void *block))
66: {
67: rt_mp_free_hook = hook;
68: }
69:
70:
71: #endif
72:
73: 74: 75:
76:
77:
78:
79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90:
91: rt_err_t rt_mp_init(struct rt_mempool *mp,
92: const char *name,
93: void *start,
94: rt_size_t size,
95: rt_size_t block_size)
96: {
97: rt_uint8_t *block_ptr;
98: register rt_base_t offset;
99:
100:
101: RT_ASSERT(mp != RT_NULL);
102:
103:
104: rt_object_init(&(mp->parent), RT_Object_Class_MemPool, name);
105:
106:
107: mp->start_address = start;
108: mp->size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
109:
110:
111: block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
112: mp->block_size = block_size;
113:
114:
115: mp->block_total_count = mp->size / (mp->block_size + sizeof(rt_uint8_t *));
116: mp->block_free_count = mp->block_total_count;
117:
118:
119: rt_list_init(&(mp->suspend_thread));
120: mp->suspend_thread_count = 0;
121:
122:
123: block_ptr = (rt_uint8_t *)mp->start_address;
124: for (offset = 0; offset < mp->block_total_count; offset ++)
125: {
126: *(rt_uint8_t **)(block_ptr + offset * (block_size + sizeof(rt_uint8_t *))) =
127: (rt_uint8_t *)(block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8_t *)));
128: }
129:
130: *(rt_uint8_t **)(block_ptr + (offset - 1) * (block_size + sizeof(rt_uint8_t *))) =
131: RT_NULL;
132:
133: mp->block_list = block_ptr;
134:
135: return RT_EOK;
136: } « end rt_mp_init »
137: RTM_EXPORT(rt_mp_init);
138:
139: 140: 141: 142: 143: 144: 145:
146: rt_err_t rt_mp_detach(struct rt_mempool *mp)
147: {
148: struct rt_thread *thread;
149: register rt_ubase_t temp;
150:
151:
152: RT_ASSERT(mp != RT_NULL);
153:
154:
155: while (!rt_list_isempty(&(mp->suspend_thread)))
156: {
157:
158: temp = rt_hw_interrupt_disable();
159:
160:
161: thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
162:
163: thread->error = -RT_ERROR;
164:
165: 166: 167: 168: 169:
170: rt_thread_resume(thread);
171:
172:
173: mp->suspend_thread_count --;
174:
175:
176: rt_hw_interrupt_enable(temp);
177: } « end while !rt_list_isempty(&(mp... »
178:
179:
180: rt_object_detach(&(mp->parent));
181:
182: return RT_EOK;
183: } « end rt_mp_detach »
184: RTM_EXPORT(rt_mp_detach);
185:
186: #ifdef RT_USING_HEAP
187: 188: 189: 190: 191: 192: 193: 194: 195: 196:
197: rt_mp_t rt_mp_create(const char *name,
198: rt_size_t block_count,
199: rt_size_t block_size)
200: {
201: rt_uint8_t *block_ptr;
202: struct rt_mempool *mp;
203: register rt_base_t offset;
204:
205: RT_DEBUG_NOT_IN_INTERRUPT;
206:
207:
208: mp = (struct rt_mempool *)rt_object_allocate(RT_Object_Class_MemPool, name);
209:
210: if (mp == RT_NULL)
211: return RT_NULL;
212:
213:
214: block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
215: mp->block_size = block_size;
216: mp->size = (block_size + sizeof(rt_uint8_t *)) * block_count;
217:
218:
219: mp->start_address = rt_malloc((block_size + sizeof(rt_uint8_t *)) *
220: block_count);
221: if (mp->start_address == RT_NULL)
222: {
223:
224: rt_object_delete(&(mp->parent));
225:
226: return RT_NULL;
227: }
228:
229: mp->block_total_count = block_count;
230: mp->block_free_count = mp->block_total_count;
231:
232:
233: rt_list_init(&(mp->suspend_thread));
234: mp->suspend_thread_count = 0;
235:
236:
237: block_ptr = (rt_uint8_t *)mp->start_address;
238: for (offset = 0; offset < mp->block_total_count; offset ++)
239: {
240: *(rt_uint8_t **)(block_ptr + offset * (block_size + sizeof(rt_uint8_t *)))
241: = block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8_t *));
242: }
243:
244: *(rt_uint8_t **)(block_ptr + (offset - 1) * (block_size + sizeof(rt_uint8_t *)))
245: = RT_NULL;
246:
247: mp->block_list = block_ptr;
248:
249: return mp;
250: } « end rt_mp_create »
251: RTM_EXPORT(rt_mp_create);
252:
253: 254: 255: 256: 257: 258: 259:
260: rt_err_t rt_mp_delete(rt_mp_t mp)
261: {
262: struct rt_thread *thread;
263: register rt_ubase_t temp;
264:
265: RT_DEBUG_NOT_IN_INTERRUPT;
266:
267:
268: RT_ASSERT(mp != RT_NULL);
269:
270:
271: while (!rt_list_isempty(&(mp->suspend_thread)))
272: {
273:
274: temp = rt_hw_interrupt_disable();
275:
276:
277: thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
278:
279: thread->error = -RT_ERROR;
280:
281: 282: 283: 284: 285:
286: rt_thread_resume(thread);
287:
288:
289: mp->suspend_thread_count --;
290:
291:
292: rt_hw_interrupt_enable(temp);
293: } « end while !rt_list_isempty(&(mp... »
294:
295: #if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
296:
297: if (mp->parent.flag & RT_OBJECT_FLAG_MODULE)
298: rt_module_free(mp->parent.module_id, mp->start_address);
299: else
300: #endif
301:
302:
303: rt_free(mp->start_address);
304:
305:
306: rt_object_delete(&(mp->parent));
307:
308: return RT_EOK;
309: } « end rt_mp_delete »
310: RTM_EXPORT(rt_mp_delete);
311: #endif
312:
313: 314: 315: 316: 317: 318: 319: 320:
321: void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
322: {
323: rt_uint8_t *block_ptr;
324: register rt_base_t level;
325: struct rt_thread *thread;
326:
327:
328: level = rt_hw_interrupt_disable();
329:
330: if (mp->block_free_count)
331: {
332:
333: mp->block_free_count --;
334:
335:
336: block_ptr = mp->block_list;
337: mp->block_list = *(rt_uint8_t **)block_ptr;
338:
339:
340: *(rt_uint8_t **)block_ptr = (rt_uint8_t *)mp;
341: }
342: else
343: {
344:
345: if (time == 0)
346: {
347:
348: rt_hw_interrupt_enable(level);
349:
350: return RT_NULL;
351: }
352: else
353: {
354: RT_DEBUG_NOT_IN_INTERRUPT;
355:
356:
357: thread = rt_thread_self();
358:
359:
360: rt_thread_suspend(thread);
361: rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist));
362: mp->suspend_thread_count ++;
363:
364: if (time > 0)
365: {
366:
367: rt_timer_control(&(thread->thread_timer),
368: RT_TIMER_CTRL_SET_TIME,
369: &time);
370: rt_timer_start(&(thread->thread_timer));
371: }
372:
373:
374: rt_hw_interrupt_enable(level);
375:
376:
377: rt_schedule();
378:
379: if (thread->error != RT_EOK)
380: return RT_NULL;
381:
382:
383: level = rt_hw_interrupt_disable();
384:
385:
386: mp->block_free_count --;
387:
388:
389: block_ptr = mp->block_list;
390: mp->block_list = *(rt_uint8_t **)block_ptr;
391:
392:
393: *(rt_uint8_t **)block_ptr = (rt_uint8_t *)mp;
394: } « end else »
395: } « end else »
396:
397:
398: rt_hw_interrupt_enable(level);
399:
400: RT_OBJECT_HOOK_CALL(rt_mp_alloc_hook,
401: (mp, (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *))));
402:
403: return (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *));
404: } « end rt_mp_alloc »
405: RTM_EXPORT(rt_mp_alloc);
406:
407: 408: 409: 410: 411:
412: void rt_mp_free(void *block)
413: {
414: rt_uint8_t **block_ptr;
415: struct rt_mempool *mp;
416: struct rt_thread *thread;
417: register rt_base_t level;
418:
419:
420: block_ptr = (rt_uint8_t **)((rt_uint8_t *)block - sizeof(rt_uint8_t *));
421: mp = (struct rt_mempool *)*block_ptr;
422:
423: RT_OBJECT_HOOK_CALL(rt_mp_free_hook, (mp, block));
424:
425:
426: level = rt_hw_interrupt_disable();
427:
428:
429: mp->block_free_count ++;
430:
431:
432: *block_ptr = mp->block_list;
433: mp->block_list = (rt_uint8_t *)block_ptr;
434:
435: if (mp->suspend_thread_count > 0)
436: {
437:
438: thread = rt_list_entry(mp->suspend_thread.next,
439: struct rt_thread,
440: tlist);
441:
442:
443: thread->error = RT_EOK;
444:
445:
446: rt_thread_resume(thread);
447:
448:
449: mp->suspend_thread_count --;
450:
451:
452: rt_hw_interrupt_enable(level);
453:
454:
455: rt_schedule();
456:
457: return;
458: } « end if mp->suspend_thread_co... »
459:
460:
461: rt_hw_interrupt_enable(level);
462: } « end rt_mp_free »
463: RTM_EXPORT(rt_mp_free);
464:
465:
466:
467: #endif
468: