1 /* 2 * Copyright 2002, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #include <MediaDefs.h> 6 #include <Autolock.h> 7 #include "BufferManager.h" 8 #include "SharedBufferList.h" 9 #include "debug.h" 10 11 BufferManager::BufferManager() 12 : fSharedBufferList(_shared_buffer_list::Clone()), 13 fSharedBufferListId(-1), 14 fNextBufferId(1), 15 fLocker(new BLocker("buffer manager locker")), 16 fBufferInfoMap(new Map<media_buffer_id, buffer_info>) 17 { 18 fSharedBufferListId = area_for(fSharedBufferList); 19 } 20 21 BufferManager::~BufferManager() 22 { 23 fSharedBufferList->Unmap(); 24 delete fLocker; 25 delete fBufferInfoMap; 26 } 27 28 area_id 29 BufferManager::SharedBufferListID() 30 { 31 return fSharedBufferListId; 32 } 33 34 status_t 35 BufferManager::RegisterBuffer(team_id teamid, media_buffer_id bufferid, 36 size_t *size, int32 *flags, size_t *offset, area_id *area) 37 { 38 BAutolock lock(fLocker); 39 40 TRACE("RegisterBuffer team = %ld, bufferid = %ld\n", teamid, bufferid); 41 42 buffer_info *info; 43 if (!fBufferInfoMap->Get(bufferid, &info)) { 44 FATAL("failed to register buffer! team = %ld, bufferid = %ld\n", teamid, bufferid); 45 PrintToStream(); 46 return B_ERROR; 47 } 48 49 info->teams.Insert(teamid); 50 51 *area = info->area; 52 *offset = info->offset; 53 *size = info->size, 54 *flags = info->flags; 55 56 PrintToStream(); 57 return B_OK; 58 } 59 60 status_t 61 BufferManager::RegisterBuffer(team_id teamid, size_t size, int32 flags, size_t offset, area_id area, 62 media_buffer_id *bufferid) 63 { 64 BAutolock lock(fLocker); 65 TRACE("RegisterBuffer team = %ld, areaid = %ld, offset = %ld, size = %ld\n", teamid, area, offset, size); 66 67 void *adr; 68 area_id newarea; 69 70 newarea = clone_area("media_server cloned buffer", &adr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area); 71 if (newarea <= B_OK) { 72 FATAL("RegisterBuffer: failed to clone buffer! error = %#lx, team = %ld, areaid = %ld, offset = %ld, size = %ld\n", newarea, teamid, area, offset, size); 73 return B_ERROR; 74 } 75 76 buffer_info info; 77 78 *bufferid = fNextBufferId; 79 info.id = fNextBufferId; 80 info.area = newarea; 81 info.offset = offset; 82 info.size = size; 83 info.flags = flags; 84 info.teams.Insert(teamid); 85 fBufferInfoMap->Insert(fNextBufferId, info); 86 87 TRACE("RegisterBuffer: done, bufferid = %ld\n", fNextBufferId); 88 89 fNextBufferId += 1; 90 91 PrintToStream(); 92 return B_OK; 93 } 94 95 status_t 96 BufferManager::UnregisterBuffer(team_id teamid, media_buffer_id bufferid) 97 { 98 BAutolock lock(fLocker); 99 TRACE("UnregisterBuffer: team = %ld, bufferid = %ld\n", teamid, bufferid); 100 101 buffer_info *info; 102 int index; 103 104 if (!fBufferInfoMap->Get(bufferid, &info)) { 105 FATAL("UnregisterBuffer: failed to unregister buffer! team = %ld, bufferid = %ld\n", teamid, bufferid); 106 PrintToStream(); 107 return B_ERROR; 108 } 109 110 index = info->teams.Find(teamid); 111 if (index < 0) { 112 FATAL("UnregisterBuffer: failed to find team = %ld belonging to bufferid = %ld\n", teamid, bufferid); 113 PrintToStream(); 114 return B_ERROR; 115 } 116 117 if (!info->teams.Remove(index)) { 118 FATAL("UnregisterBuffer: failed to remove team = %ld from bufferid = %ld\n", teamid, bufferid); 119 PrintToStream(); 120 return B_ERROR; 121 } 122 TRACE("UnregisterBuffer: team = %ld removed from bufferid = %ld\n", teamid, bufferid); 123 124 if (info->teams.IsEmpty()) { 125 126 if (!fBufferInfoMap->Remove(bufferid)) { 127 FATAL("UnregisterBuffer: failed to remove bufferid = %ld\n", bufferid); 128 PrintToStream(); 129 return B_ERROR; 130 } 131 132 TRACE("UnregisterBuffer: bufferid = %ld removed\n", bufferid); 133 } 134 135 return B_OK; 136 } 137 138 void 139 BufferManager::CleanupTeam(team_id team) 140 { 141 BAutolock lock(fLocker); 142 buffer_info *info; 143 144 TRACE("BufferManager::CleanupTeam: team %ld\n", team); 145 146 PrintToStream(); 147 148 for (fBufferInfoMap->Rewind(); fBufferInfoMap->GetNext(&info); ) { 149 team_id *otherteam; 150 for (info->teams.Rewind(); info->teams.GetNext(&otherteam); ) { 151 if (team == *otherteam) { 152 FATAL("BufferManager::CleanupTeam: removing team %ld from buffer id %ld\n", team, info->id); 153 info->teams.RemoveCurrent(); 154 } 155 } 156 if (info->teams.IsEmpty()) { 157 FATAL("BufferManager::CleanupTeam: removing buffer id %ld that has no teams\n", info->id); 158 fBufferInfoMap->RemoveCurrent(); 159 } 160 } 161 162 PrintToStream(); 163 } 164 165 void 166 BufferManager::PrintToStream() 167 { 168 BAutolock lock(fLocker); 169 buffer_info *info; 170 team_id *team; 171 TRACE("BufferManager: list of buffers follows:\n"); 172 for (fBufferInfoMap->Rewind(); fBufferInfoMap->GetNext(&info); ) { 173 TRACE(" bufferid = %ld, areaid = %ld, offset = %ld, size = %ld, flags = %#08lx\n", 174 info->id, info->area, info->offset, info->size, info->flags); 175 for (info->teams.Rewind(); info->teams.GetNext(&team); ) { 176 TRACE(" team = %ld", *team); 177 } 178 TRACE("\n"); 179 } 180 TRACE("BufferManager: list end\n"); 181 } 182