code: func (c *cmd) setupSemaphore(client *api.Client, limit int, prefix, name string,
  	oneshot bool, wait time.Duration, retry int) (*LockUnlock, error) {
  	if c.verbose {
  		c.UI.Info(fmt.Sprintf("Setting up semaphore (limit %d) at prefix: %s", limit, prefix))
  	}
  	opts := api.SemaphoreOptions{
  		Prefix:           prefix,
  		Limit:            limit,
  		SessionName:      name,
  		MonitorRetries:   retry,
  		MonitorRetryTime: defaultMonitorRetryTime,
  	}
  	if oneshot {
  		opts.SemaphoreTryOnce = true
  		opts.SemaphoreWaitTime = wait
  	}
  	s, err := client.SemaphoreOpts(&opts)
  	if err != nil {
  		return nil, err
  	}
  	lu := &LockUnlock{
  		lockFn:    s.Acquire,
  		unlockFn:  s.Release,
  		cleanupFn: s.Destroy,
  		inUseErr:  api.ErrSemaphoreInUse,
  		rawOpts:   &opts,
  	}
  	return lu, nil
  }
docs: // setupSemaphore is used to setup a new Semaphore given the API client, key
  // prefix, session name, and slot holder limit. If oneshot is true then we will
  // set up for a single attempt at acquisition, using the given wait time. The
  // retry parameter sets how many 500 errors the lock monitor will tolerate
  // before giving up the semaphore.