NetBSD-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
NetBSD and ChatGPT
Hello,
I think most people have heard about the ChatGTP AI system and its
ability e.g. to write texts or accomplish programming tasks. I was
wondering if it would be able to implement something in the NetBSD
kernel and I would like to share my experiences, in case someone is
interested.
I asked if it knows semaphores and if it could show a sample API,
which it did. I then asked for an implementation for the NetBSD kernel
(syscalls were meant here for a userspace API). I received pretty much
nothing but an empty skeleton with some basic header files, an empty
"struct sem" and some function definitions without any content. It
said that the implementation is a complex task and I should consult
with an experienced specialist.
I needed to advise over and over again and the code slowly became how
it (approximately) should be. Here is what I said:
-Please add a list that will contain all semaphore structures.
-Perfect. Can you add neccessary variables to struct sem, like the
name, the id and a condvar to handle waits?
-Great. Can you add an appropriate interlock to struct sem? Also,
waits should be interruptible.
-I think for all functions except create_sem_impl, you need to walk
through the list of semaphores to look up the right struct sem.
-Regarding the lookup of struct sem, wouldn´t it be better to use
LIST_FOREACH? Also could you implement the lookup in a separate
function?
-Right, can you change the implementation functions to meet the way
they are natively implemented in NetBSD?
-That is not yet the way syscalls are implemented under NetBSD. Look
in sys/syscallargs.h how it must be done.
-Pretty good. But did you miss the SCARG macro for accessing system
call arguments?
I was impressed that this is possible. ChatGTP was able to understand
this and perform the implementation of these steps using NetBSD kernel
API. At the end I think it got a little confused and sometimes refused
to do things (too complex) or parts of the code were wrong that were
already good previously.
As I said, the last version of the code got messy. The only thing to
note is that it was able to apply the system call interface like this:
int
create_sem_impl(struct lwp *l, const netbsd_create_sem_args *uap,
register_t *retval)
{
struct sem *sem;
char *name;
int error;
error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SEMAPHORE,
KAUTH_REQ_SYSTEM_SEMAPHORE_CREATE, NULL, NULL, NULL);
if (error)
return (error);
sem = kmem_zalloc(sizeof(*sem), KM_SLEEP);
name = kmem_alloc(MAXCOMLEN + 1, KM_SLEEP);
error = copyinstr(SCARG(uap, name), name, MAXCOMLEN + 1, NULL);
...
Below is the version of the whole code which I think is best.
Stephan
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
struct sem {
int id;
char name[MAXCOMLEN + 1];
int count;
kmutex_t lock;
kcondvar_t cv;
LIST_ENTRY(sem) sem_list;
};
static LIST_HEAD(, sem) sem_head = LIST_HEAD_INITIALIZER(sem_head);
struct sem *lookup_sem(int id) {
struct sem *sem;
LIST_FOREACH(sem, &sem_head, sem_list) {
if (sem->id == id)
return sem;
}
return NULL;
}
int create_sem_impl(const char *name, int count) {
struct sem *sem;
/* Allocate memory for the semaphore */
sem = kmem_alloc(sizeof(*sem), KM_SLEEP);
if (sem == NULL)
return ENOMEM;
/* Initialize the semaphore */
sem->id = next_id++;
strlcpy(sem->name, name, sizeof(sem->name));
sem->count = count;
mutex_init(&sem->lock, MUTEX_DEFAULT, IPL_NONE);
cv_init(&sem->cv, name);
/* Add the semaphore to the list of semaphores */
LIST_INSERT_HEAD(&sem_head, sem, sem_list);
return sem->id;
}
int destroy_sem_impl(int sem_id) {
struct sem *sem;
/* Look up the semaphore in the list of semaphores */
sem = lookup_sem(sem_id);
if (sem == NULL)
return ENOENT;
/* Remove the semaphore from the list of semaphores */
LIST_REMOVE(sem, sem_list);
/* Destroy the semaphore */
mutex_destroy(&sem->lock);
cv_destroy(&sem->cv);
kmem_free(sem, sizeof(*sem));
return 0;
}
int acquire_sem_impl(int sem_id) {
struct sem *sem;
int error = 0;
/* Look up the semaphore in the list of semaphores */
sem = lookup_sem(sem_id);
if (sem == NULL)
return ENOENT;
/* Acquire the lock for the semaphore */
mutex_enter(&sem->lock);
/* Wait for the semaphore to become available */
while (sem->count == 0) {
error = cv_wait_sig(&sem->cv, &sem->lock);
if (error)
break;
}
/* Decrement the count if the semaphore is available */
if (!error) sem->count--;
/* Release the lock for the semaphore */
mutex_exit(&sem->lock);
return error;
}
int release_sem_impl(int sem_id) {
struct sem *sem;
/* Look up the semaphore in the list of semaphores */
sem = lookup_sem(sem_id);
if (sem == NULL)
return ENOENT;
/* Acquire the lock for the semaphore */
mutex_enter(&sem->lock);
/* Increment the count for the semaphore */
sem->count++;
/* Signal the semaphore */
cv_signal(&sem->cv);
/* Release the lock for the semaphore */
mutex_exit(&sem->lock);
return 0;
}
Home |
Main Index |
Thread Index |
Old Index