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