bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v7 1/2 hurd] libirqhelp: Add library


From: Samuel Thibault
Subject: Re: [PATCH v7 1/2 hurd] libirqhelp: Add library
Date: Mon, 4 Mar 2024 00:53:16 +0100
User-agent: NeoMutt/20170609 (1.8.3)

Damien Zammit, le sam. 02 mars 2024 10:31:50 +0000, a ecrit:
> +static error_t
> +get_acpi(void)
> +{
> +  error_t err = 0;
> +  mach_port_t tryacpi, device_master;
> +
> +  acpidev = MACH_PORT_NULL;

This looks odd. If we had a previous port in acpidev, we want to
deallocate it, not forget it.

> +  err = get_privileged_ports (0, &device_master);
> +  if (!err)
> +    {
> +      err = device_open (device_master, D_READ, "acpi", &tryacpi);
> +      mach_port_deallocate (mach_task_self (), device_master);
> +      if (!err)
> +        {
> +       acpidev = tryacpi;
> +          return 0;
> +        }
> +    }
> +
> +  tryacpi = file_name_lookup (_SERVERS_ACPI, O_RDONLY, 0);
> +  if (tryacpi == MACH_PORT_NULL)
> +    return ENODEV;
> +
> +  acpidev = tryacpi;
> +  return 0;
> +}
> +
> +static error_t
> +get_irq(void)
> +{
> +  error_t err = 0;
> +  mach_port_t tryirq, device_master;
> +
> +  irqdev = MACH_PORT_NULL;

Same here.

> +  err = get_privileged_ports (0, &device_master);
> +  if (err)
> +    return err;
> +
> +  err = device_open (device_master, D_READ|D_WRITE, "irq", &tryirq);
> +  mach_port_deallocate (mach_task_self (), device_master);
> +  if (err)
> +    return err;
> +
> +  irqdev = tryirq;
> +  return err;
> +}
> +
> +error_t
> +irqhelp_init(void)
> +{
> +  static bool inited = false;
> +  error_t err;
> +
> +  if (inited)
> +    {
> +      log_error("already inited\n");
> +      return 0;

But we already have a guard against several initializations. So I don't
see the point of setting the ports to MACH_PORT_NULL? Or else you meant
to statically initalize them to MACH_PORT_NULL? (which will be much more
efficient).

> +    }
> +
> +  err = get_irq();
> +  if (err)
> +    {
> +      log_error("cannot grab irq device\n");
> +      return err;
> +    }
> +
> +  err = get_acpi();
> +  if (err)
> +    {
> +      log_error("cannot grab acpi device\n");
> +      return err;
> +    }
> +
> +  inited = true;
> +  return 0;
> +}
> +
> +void *
> +irqhelp_server_loop(void *arg)
> +{
> +  struct irq *irq = (struct irq *)arg;
> +  mach_port_t master_host;
> +  mach_port_t pset, psetcntl;
> +  error_t err;
> +
> +  if (!irq)
> +    {
> +      log_error("cannot start this irq thread\n");
> +      return NULL;
> +    }
> +
> +  err = get_privileged_ports (&master_host, 0);
> +  if (err)
> +    {
> +      log_error("cannot get master_host port\n");
> +      return NULL;
> +    }
> +
> +  err = thread_get_assignment (mach_thread_self (), &pset);
> +  if (err)
> +    goto fail;
> +
> +  err = host_processor_set_priv (master_host, pset, &psetcntl);
> +  if (err)
> +    goto fail;
> +
> +  thread_max_priority (mach_thread_self (), psetcntl, 0);
> +  err = thread_priority (mach_thread_self (), IRQ_THREAD_PRIORITY, 0);
> +  if (err)
> +    goto fail;
> +
> +  mach_port_deallocate (mach_task_self (), master_host);
> +
> +  int interrupt_demuxer (mach_msg_header_t *inp,
> +                      mach_msg_header_t *outp)
> +  {
> +    static bool printed0 = false;
> +    static bool printed1 = false;

Better put them in their respective blocks.

> +    device_intr_notification_t *n = (device_intr_notification_t *) inp;
> +
> +    ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY;
> +    if (n->intr_header.msgh_id != DEVICE_INTR_NOTIFY)
> +      {
> +     if (!printed0)
> +       {
> +         log_error("msg received is not an interrupt\n");
> +            printed0 = true;
> +       }
> +     return 0;
> +      }
> +
> +    /* FIXME: id <-> gsi now has an indirection, assuming 1:1 */
> +    if (n->id != irq->gsi)
> +      {
> +     if (!printed1)
> +       {
> +         log_error("interrupt expected on irq %d arrived on irq %d\n", 
> irq->gsi, n->id);
> +         printed1 = true;
> +       }
> +     return 0;
> +      }
> +
> +    /* wait if irq disabled */
> +    pthread_mutex_lock (&irq->irqlock);
> +    while (!irq->enabled)
> +      pthread_cond_wait (&irq->irqcond, &irq->irqlock);
> +    pthread_mutex_unlock (&irq->irqlock);
> + 
> +    /* call handler */
> +    irq->handler(irq->context);

You probably want to add an if (!irq->shutdown) before this? Otherwise
after the application called irqhelp_remove_interrupt_handler, the
handler will still be called once.

> +    /* ACK interrupt */
> +    device_intr_ack (irqdev, irq->port, MACH_MSG_TYPE_MAKE_SEND);

This might be spurious as well in the irq->shutdown case?

> +    if (irq->shutdown)
> +      mach_port_deallocate (mach_task_self (), irq->port);
> +
> +    return 1;
> +  }
> +
> +  /* Server loop */
> +  mach_msg_server (interrupt_demuxer, 0, irq->port);
> +  goto done;
> +
> +fail:
> +  log_error("failed to register irq %d\n", irq->gsi);
> +
> +done:
> +  pthread_cond_destroy(&irq->irqcond);
> +  pthread_mutex_destroy(&irq->irqlock);
> +  free(irq);
> +  return NULL;
> +}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]