Implementation of the kernel part of the image API.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2413 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4a05764e4b
commit
515a4a6590
265
src/kernel/core/image.c
Normal file
265
src/kernel/core/image.c
Normal file
@ -0,0 +1,265 @@
|
||||
/* User Runtime Loader support in the kernel
|
||||
**
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <kimage.h>
|
||||
#include <thread_types.h>
|
||||
#include <thread.h>
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// ToDo: register kernel images as well
|
||||
|
||||
struct image {
|
||||
struct image *next;
|
||||
struct image *prev;
|
||||
image_info info;
|
||||
};
|
||||
|
||||
|
||||
static image_id gNextImageID = 1;
|
||||
|
||||
|
||||
/** Registers an image with the specified team.
|
||||
*/
|
||||
|
||||
image_id
|
||||
register_image(team_id teamID, image_info *_info, size_t size)
|
||||
{
|
||||
image_id id = atomic_add(&gNextImageID, 1);
|
||||
struct image *image;
|
||||
struct team *team;
|
||||
cpu_status state;
|
||||
|
||||
image = malloc(sizeof(image_info));
|
||||
if (image == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memcpy(&image->info, _info, sizeof(image_info));
|
||||
|
||||
state = disable_interrupts();
|
||||
GRAB_TEAM_LOCK();
|
||||
|
||||
team = team_get_team_struct_locked(teamID);
|
||||
if (team) {
|
||||
image->info.id = id;
|
||||
insque(image, &team->image_queue);
|
||||
}
|
||||
|
||||
RELEASE_TEAM_LOCK();
|
||||
restore_interrupts(state);
|
||||
|
||||
dprintf("register_image(team = %ld, image id = %ld, image = %p\n", teamID, id, image);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/** Unregisters an image from the specified team.
|
||||
*/
|
||||
|
||||
status_t
|
||||
unregister_image(team_id teamID, image_id id)
|
||||
{
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
struct image *image;
|
||||
struct team *team;
|
||||
cpu_status state;
|
||||
|
||||
state = disable_interrupts();
|
||||
GRAB_TEAM_LOCK();
|
||||
|
||||
team = team_get_team_struct_locked(teamID);
|
||||
if (team) {
|
||||
kqueue_foreach (&team->image_queue, image) {
|
||||
if (image->info.id == id) {
|
||||
remque(image);
|
||||
free(image);
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RELEASE_TEAM_LOCK();
|
||||
restore_interrupts(state);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** Counts the registered images from the specified team.
|
||||
* The team lock must be hold when you call this function.
|
||||
*/
|
||||
|
||||
int32
|
||||
count_images(struct team *team)
|
||||
{
|
||||
struct image *image;
|
||||
int32 count = 0;
|
||||
|
||||
kqueue_foreach (&team->image_queue, image) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/** Removes all images from the specified team. Must only be called
|
||||
* with the team lock hold or a team that has already been removed
|
||||
* from the list (in thread_exit()).
|
||||
*/
|
||||
|
||||
status_t
|
||||
remove_images(struct team *team)
|
||||
{
|
||||
struct image *image, *nextImage;
|
||||
|
||||
ASSERT(team != NULL);
|
||||
|
||||
// can't use kqueue_foreach() because "image" gets freed
|
||||
for (image = (struct image *)team->image_queue.next;
|
||||
image != (void *)&team->image_queue; image = nextImage) {
|
||||
nextImage = image->next;
|
||||
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_get_image_info(image_id id, image_info *info, size_t size)
|
||||
{
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
struct image *image;
|
||||
struct team *team;
|
||||
cpu_status state;
|
||||
|
||||
state = disable_interrupts();
|
||||
GRAB_TEAM_LOCK();
|
||||
|
||||
team = thread_get_current_thread()->team;
|
||||
if (team) {
|
||||
kqueue_foreach (&team->image_queue, image) {
|
||||
if (image->info.id == id) {
|
||||
memcpy(info, &image->info, size);
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RELEASE_TEAM_LOCK();
|
||||
restore_interrupts(state);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_get_next_image_info(team_id teamID, int32 *cookie, image_info *info, size_t size)
|
||||
{
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
struct image *image;
|
||||
struct team *team;
|
||||
cpu_status state;
|
||||
|
||||
state = disable_interrupts();
|
||||
GRAB_TEAM_LOCK();
|
||||
|
||||
team = team_get_team_struct_locked(teamID);
|
||||
if (team) {
|
||||
int32 count = 0;
|
||||
kqueue_foreach (&team->image_queue, image) {
|
||||
if (count == *cookie) {
|
||||
memcpy(info, &image->info, size);
|
||||
status = B_OK;
|
||||
(*cookie)++;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
} else
|
||||
status = B_BAD_TEAM_ID;
|
||||
|
||||
RELEASE_TEAM_LOCK();
|
||||
restore_interrupts(state);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// Functions exported for the user space
|
||||
|
||||
|
||||
status_t
|
||||
user_unregister_image(image_id id)
|
||||
{
|
||||
return unregister_image(team_get_current_team_id(), id);
|
||||
}
|
||||
|
||||
|
||||
image_id
|
||||
user_register_image(image_info *userInfo, size_t size)
|
||||
{
|
||||
image_info info;
|
||||
|
||||
if (size != sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!CHECK_USER_ADDRESS(userInfo)
|
||||
|| user_memcpy(&info, userInfo, size) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return register_image(team_get_current_team_id(), &info, size);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
user_get_image_info(image_id id, image_info *userInfo, size_t size)
|
||||
{
|
||||
image_info info;
|
||||
status_t status;
|
||||
|
||||
if (size != sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!CHECK_USER_ADDRESS(userInfo))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status = _get_image_info(id, &info, size);
|
||||
|
||||
if (user_memcpy(userInfo, &info, size) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
user_get_next_image_info(team_id team, int32 *_cookie, image_info *userInfo, size_t size)
|
||||
{
|
||||
image_info info;
|
||||
status_t status;
|
||||
|
||||
if (size != sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!CHECK_USER_ADDRESS(userInfo) || !CHECK_USER_ADDRESS(_cookie))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status = _get_next_image_info(team, _cookie, &info, size);
|
||||
|
||||
if (user_memcpy(userInfo, &info, size) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user