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