xref: /haiku/src/servers/media/BufferManager.cpp (revision 2807c36668a1730dd59bc39de65e0b8f88cd5d0d)
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