1/* BufferPool - a buffer pool for uncached file access 2** 3** Initial version by Axel Dörfler, axeld@pinc-software.de 4** This file may be used under the terms of the OpenBeOS License. 5*/ 6 7 8#include "BufferPool.h" 9#include "Debug.h" 10 11#include <util/kernel_cpp.h> 12 13 14const uint32 kNumBuffers = 8; 15 16 17BufferPool::BufferPool() 18 : 19 fFirstFree(NULL) 20{ 21 fLock = create_sem(1, "buffer lock"); 22 fFreeBuffers = create_sem(0, "free buffers"); 23 24#ifndef USER 25 set_sem_owner(fLock, B_SYSTEM_TEAM); 26 set_sem_owner(fFreeBuffers, B_SYSTEM_TEAM); 27#endif 28} 29 30 31BufferPool::~BufferPool() 32{ 33 delete_sem(fFreeBuffers); 34 35 acquire_sem(fLock); 36 // the return value doesn't interest us anymore 37 38 void **buffer = fFirstFree; 39 while (buffer != NULL) { 40 void **nextBuffer = (void **)*buffer; 41 free(buffer); 42 buffer = nextBuffer; 43 } 44 45 delete_sem(fLock); 46} 47 48 49status_t 50BufferPool::InitCheck() 51{ 52 if (fLock < B_OK 53 || fFreeBuffers < B_OK) 54 return B_ERROR; 55 56 return B_OK; 57} 58 59 60status_t 61BufferPool::RequestBuffers(uint32 blockSize) 62{ 63 void **buffers[kNumBuffers]; 64 65 // allocate and connect buffers 66 67 for (uint32 i = 0; i < kNumBuffers; i++) { 68 buffers[i] = (void **)malloc(blockSize); 69 if (buffers[i] == NULL) { 70 // free already allocated buffers 71 for (;i-- > 0; i++) 72 free(buffers[i]); 73 RETURN_ERROR(B_NO_MEMORY); 74 } 75 if (i > 0) 76 *(buffers[i]) = buffers[i - 1]; 77 } 78 79 // add the buffers to the free buffers queue 80 81 status_t status = acquire_sem(fLock); 82 if (status == B_OK) { 83 *(buffers[0]) = fFirstFree; 84 fFirstFree = buffers[kNumBuffers - 1]; 85 release_sem(fLock); 86 release_sem_etc(fFreeBuffers, kNumBuffers, B_DO_NOT_RESCHEDULE); 87 } else { 88 for (uint32 i = 0; i < kNumBuffers; i++) 89 free(buffers[i]); 90 } 91 92 RETURN_ERROR(status); 93} 94 95 96status_t 97BufferPool::ReleaseBuffers() 98{ 99 status_t status = acquire_sem_etc(fFreeBuffers, kNumBuffers, 0, 0); 100 if (status < B_OK) 101 return status; 102 103 status = acquire_sem(fLock); 104 if (status < B_OK) 105 return status; 106 107 void **buffer = fFirstFree; 108 for (uint32 i = 0; i < kNumBuffers && buffer; i++) { 109 void **nextBuffer = (void **)*buffer; 110 111 free(buffer); 112 buffer = nextBuffer; 113 } 114 fFirstFree = buffer; 115 116 release_sem(fLock); 117 return B_OK; 118} 119 120 121status_t 122BufferPool::GetBuffer(void **_buffer) 123{ 124 status_t status = acquire_sem(fFreeBuffers); 125 if (status < B_OK) 126 return status; 127 128 if ((status = acquire_sem(fLock)) < B_OK) { 129 release_sem(fFreeBuffers); 130 return status; 131 } 132 133 void **buffer = fFirstFree; 134 fFirstFree = (void **)*buffer; 135 136 release_sem(fLock); 137 138 *_buffer = (void *)buffer; 139 return B_OK; 140} 141 142 143status_t 144BufferPool::PutBuffer(void *_buffer) 145{ 146 void **buffer = (void **)_buffer; 147 if (buffer == NULL) 148 return B_BAD_VALUE; 149 150 status_t status = acquire_sem(fLock); 151 if (status < B_OK) 152 return status; 153 154 *buffer = fFirstFree; 155 fFirstFree = buffer; 156 157 release_sem(fLock); 158 release_sem(fFreeBuffers); 159 160 return B_OK; 161} 162 163