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