Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASYNC_start_job: more readable documentation for handling ASYNC* APIs #23941

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 29 additions & 8 deletions doc/man3/ASYNC_start_job.pod
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ ASYNC_stack_alloc_fn, ASYNC_stack_free_fn, ASYNC_set_mem_functions, ASYNC_get_me
OpenSSL implements asynchronous capabilities through an B<ASYNC_JOB>. This
represents code that can be started and executes until some event occurs. At
that point the code can be paused and control returns to user code until some
subsequent event indicates that the job can be resumed.
subsequent event indicates that the job can be resumed. It's OpenSSL
specific implementation of cooperative multitasking.

The creation of an B<ASYNC_JOB> is a relatively expensive operation. Therefore,
for efficiency reasons, jobs can be created up front and reused many times. They
Expand Down Expand Up @@ -91,7 +92,8 @@ can be performed (if desired) and the job restarted at a later time. To restart
a job call ASYNC_start_job() again passing the job handle in I<*job>. The
I<func>, I<args> and I<size> parameters will be ignored when restarting a job.
When restarting a job ASYNC_start_job() B<must> be called from the same thread
that the job was originally started from.
that the job was originally started from. B<ASYNC_WAIT_CTX> is used to
know when a job is ready to be restarted.

=item B<ASYNC_FINISH>

Expand All @@ -115,13 +117,15 @@ ASYNC_pause_job() is called whilst not within the context of a job then no
action is taken and ASYNC_pause_job() returns immediately.

ASYNC_get_wait_ctx() can be used to get a pointer to the B<ASYNC_WAIT_CTX>
for the I<job>. B<ASYNC_WAIT_CTX>s contain two different ways to notify
for the I<job> (see L<ASYNC_WAIT_CTX_new(3)>).
B<ASYNC_WAIT_CTX>s contain two different ways to notify
applications that a job is ready to be resumed. One is a "wait" file
descriptor, and the other is a "callback" mechanism.

The "wait" file descriptor associated with B<ASYNC_WAIT_CTX> is used for
applications to wait for the file descriptor to be ready for "read" using a
system function call such as select or poll (being ready for "read" indicates
system function call such as select(2) or poll(2) (being ready for "read"
indicates
that the job should be resumed). If no file descriptor is made available then
an application will have to periodically "poll" the job by attempting to restart
it to see if it is ready to continue.
Expand Down Expand Up @@ -236,6 +240,13 @@ The following example demonstrates how to use most of the core async APIs:
msg = (unsigned char *)arg;
printf("Passed in message is: %s\n", msg);

/*
* Create a way to inform the calling thread when this job is ready
* to resume, in this example we're using file descriptors.
* For offloading the task to an asynchronous ENGINE it's not necessary,
* the ENGINE should handle that internally.
*/

if (pipe(pipefds) != 0) {
printf("Failed to create pipe\n");
return 0;
Expand All @@ -250,17 +261,23 @@ The following example demonstrates how to use most of the core async APIs:
pipefds[0], wptr, cleanup);

/*
* Normally some external event would cause this to happen at some
* Normally some external event (like a network read being ready,
* disk access being finished, or some hardware offload operation
* completing) would cause this to happen at some
* later point - but we do it here for demo purposes, i.e.
* immediately signalling that the job is ready to be woken up after
* we return to main via ASYNC_pause_job().
*/
write(pipefds[1], &buf, 1);

/* Return control back to main */
/*
* Return control back to main just before calling a blocking
* method. The main thread will wait until pipefds[0] is ready
* for reading before returning control to this thread.
*/
ASYNC_pause_job();

/* Clear the wake signal */
/* Perform the blocking call (it won't block with this example code) */
read(pipefds[0], &buf, 1);

printf ("Resumed the job after a pause\n");
Expand Down Expand Up @@ -300,7 +317,9 @@ The following example demonstrates how to use most of the core async APIs:
goto end;
}

/* Wait for the job to be woken */
/* Get the file descriptor we can use to wait for the job
* to be ready to be woken up
*/
printf("Waiting for the job to be woken up\n");

if (!ASYNC_WAIT_CTX_get_all_fds(ctx, NULL, &numfds)
Expand All @@ -311,6 +330,8 @@ The following example demonstrates how to use most of the core async APIs:
ASYNC_WAIT_CTX_get_all_fds(ctx, &waitfd, &numfds);
FD_ZERO(&waitfdset);
FD_SET(waitfd, &waitfdset);

/* Wait for the job to be ready for wakeup */
mattcaswell marked this conversation as resolved.
Show resolved Hide resolved
select(waitfd + 1, &waitfdset, NULL, NULL, NULL);
}

Expand Down