Mô hình luồng

Các phương thức được đánh dấu là oneway sẽ không bị chặn. Đối với các phương thức không được đánh dấu là oneway , lệnh gọi phương thức của máy khách sẽ chặn cho đến khi máy chủ hoàn thành việc thực thi hoặc được gọi là lệnh gọi lại đồng bộ (tùy điều kiện nào đến trước). Việc triển khai phương thức máy chủ có thể gọi tối đa một lệnh gọi lại đồng bộ; các cuộc gọi lại bổ sung sẽ bị loại bỏ và ghi lại dưới dạng lỗi. Nếu một phương thức được cho là trả về các giá trị thông qua lệnh gọi lại và không gọi lại lệnh gọi lại của nó thì điều này sẽ được ghi lại là lỗi và được báo cáo là lỗi truyền tải tới máy khách.

Chủ đề ở chế độ chuyển tiếp

Ở chế độ chuyển tiếp, hầu hết các cuộc gọi đều đồng bộ. Tuy nhiên, để duy trì hành vi mong muốn mà các cuộc gọi oneway không chặn máy khách, một luồng được tạo cho mỗi tiến trình. Để biết chi tiết, hãy xem tổng quan về HIDL .

Chủ đề trong HAL liên kết

Để phục vụ các cuộc gọi RPC đến (bao gồm các cuộc gọi lại không đồng bộ từ HAL đến người dùng HAL) và thông báo ngừng hoạt động, một nhóm luồng được liên kết với mỗi quy trình sử dụng HIDL. Nếu một quy trình duy nhất triển khai nhiều giao diện HIDL và/hoặc trình xử lý thông báo tử vong, thì nhóm luồng của nó sẽ được chia sẻ giữa tất cả chúng. Khi một tiến trình nhận được một lệnh gọi phương thức đến từ một máy khách, nó sẽ chọn một luồng còn trống từ threadpool và thực hiện lệnh gọi trên luồng đó. Nếu không có chủ đề miễn phí nào, nó sẽ chặn cho đến khi có chủ đề trống.

Nếu máy chủ chỉ có một luồng thì các lệnh gọi vào máy chủ sẽ được hoàn thành theo thứ tự. Một máy chủ có nhiều hơn một luồng có thể hoàn thành các cuộc gọi không theo thứ tự ngay cả khi máy khách chỉ có một luồng. Tuy nhiên, đối với một đối tượng giao diện nhất định, các cuộc gọi oneway được đảm bảo theo thứ tự (xem Mô hình phân luồng máy chủ ). Đối với máy chủ đa luồng lưu trữ nhiều giao diện, các cuộc gọi oneway đến các giao diện khác nhau có thể được xử lý đồng thời với nhau hoặc các cuộc gọi chặn khác.

Nhiều cuộc gọi lồng nhau sẽ được gửi trên cùng một chuỗi hwbinder. Ví dụ: nếu một tiến trình (A) thực hiện lệnh gọi đồng bộ từ luồng hwbinder đến tiến trình (B), sau đó tiến trình (B) thực hiện lệnh gọi đồng bộ trở lại tiến trình (A), cuộc gọi sẽ được thực thi trên luồng hwbinder ban đầu trong (A) bị chặn trong cuộc gọi ban đầu. Sự tối ưu hóa này giúp có thể có một máy chủ luồng đơn có thể xử lý các cuộc gọi lồng nhau, nhưng nó không mở rộng đến các trường hợp cuộc gọi đi qua một chuỗi cuộc gọi IPC khác. Ví dụ: nếu quy trình (B) đã thực hiện lệnh gọi binder/vndbinder được gọi đến một quy trình (C) và sau đó xử lý (C) gọi lại vào (A), thì nó không thể được phục vụ trên luồng ban đầu trong (A).

Mô hình phân luồng máy chủ

Ngoại trừ chế độ chuyển tiếp, việc triển khai giao diện HIDL trên máy chủ hoạt động trong một quy trình khác với máy khách và cần một hoặc nhiều luồng chờ lệnh gọi phương thức đến. Các chủ đề này là threadpool của máy chủ; máy chủ có thể quyết định số lượng luồng nó muốn chạy trong luồng của nó và có thể sử dụng kích thước luồng của một luồng để tuần tự hóa tất cả các cuộc gọi trên giao diện của nó. Nếu máy chủ có nhiều hơn một luồng trong threadpool, nó có thể nhận các cuộc gọi đến đồng thời trên bất kỳ giao diện nào của nó (trong C++, điều này có nghĩa là dữ liệu dùng chung phải được khóa cẩn thận).

Các cuộc gọi một chiều vào cùng một giao diện được tuần tự hóa. Nếu máy khách đa luồng gọi method1method2 trên giao diện IFoomethod3 trên giao diện IBar thì method1method2 sẽ luôn được tuần tự hóa, nhưng method3 có thể chạy song song với method1method2 .

Một luồng thực thi của một máy khách có thể gây ra sự thực thi đồng thời trên một máy chủ có nhiều luồng theo hai cách:

  • cuộc gọi oneway không bị chặn. Nếu cuộc gọi oneway được thực hiện và sau đó một cuộc gọi không một oneway được gọi, máy chủ có thể thực hiện đồng thời cuộc gọi oneway và cuộc gọi không oneway .
  • Các phương thức máy chủ truyền dữ liệu trở lại bằng lệnh gọi lại đồng bộ có thể bỏ chặn máy khách ngay khi lệnh gọi lại được gọi từ máy chủ.

Đối với cách thứ hai, bất kỳ mã nào trong hàm máy chủ thực thi sau lệnh gọi lại đều có thể thực thi đồng thời, trong đó máy chủ sẽ xử lý các lệnh gọi tiếp theo từ máy khách. Điều này bao gồm mã trong hàm máy chủ và các hàm hủy tự động thực thi ở cuối hàm. Nếu máy chủ có nhiều hơn một luồng trong nhóm luồng của nó thì các vấn đề tương tranh sẽ phát sinh ngay cả khi các lệnh gọi đến chỉ từ một luồng máy khách duy nhất. (Nếu bất kỳ HAL nào được một tiến trình phân phối cần nhiều luồng, thì tất cả các HAL sẽ có nhiều luồng vì nhóm luồng được chia sẻ cho mỗi tiến trình.)

Ngay khi máy chủ gọi lệnh gọi lại được cung cấp, phương tiện vận chuyển có thể gọi lệnh gọi lại đã triển khai trên máy khách và bỏ chặn máy khách. Máy khách tiến hành song song với bất cứ điều gì việc triển khai máy chủ thực hiện sau khi nó gọi lệnh gọi lại (có thể bao gồm các hàm hủy đang chạy). Mã trong chức năng máy chủ sau khi gọi lại không còn chặn máy khách nữa (miễn là luồng máy chủ có đủ luồng để xử lý các cuộc gọi đến), nhưng có thể được thực thi đồng thời với các cuộc gọi trong tương lai từ máy khách (trừ khi luồng máy chủ chỉ có một luồng ).

Ngoài các cuộc gọi lại đồng bộ, các cuộc gọi oneway từ máy khách đơn luồng có thể được xử lý đồng thời bởi một máy chủ có nhiều luồng trong nhóm luồng của nó, nhưng chỉ khi các cuộc gọi oneway đó được thực thi trên các giao diện khác nhau. các cuộc gọi oneway trên cùng một giao diện luôn được tuần tự hóa.

Lưu ý: Chúng tôi đặc biệt khuyến khích các hàm máy chủ quay trở lại ngay sau khi chúng gọi hàm gọi lại.

Ví dụ (trong C++):

Return<void> someMethod(someMethod_cb _cb) {
    // Do some processing, then call callback with return data
    hidl_vec<uint32_t> vec = ...
    _cb(vec);
    // At this point, the client's callback will be called,
    // and the client will resume execution.
    ...
    return Void(); // is basically a no-op
};

Mô hình luồng khách hàng

Mô hình phân luồng trên máy khách khác nhau giữa các cuộc gọi không chặn (các chức năng được đánh dấu bằng từ khóa oneway ) và các cuộc gọi chặn (các chức năng không có từ khóa oneway được chỉ định).

Chặn cuộc gọi

Để chặn cuộc gọi, máy khách sẽ chặn cho đến khi một trong những điều sau xảy ra:

  • Xảy ra lỗi vận chuyển; đối tượng Return chứa trạng thái lỗi có thể được truy xuất bằng Return::isOk() .
  • Việc triển khai máy chủ sẽ gọi lại lệnh gọi lại (nếu có).
  • Việc triển khai máy chủ trả về một giá trị (nếu không có tham số gọi lại).

Trong trường hợp thành công, hàm gọi lại mà máy khách chuyển dưới dạng đối số luôn được máy chủ gọi trước khi hàm đó tự trả về. Lệnh gọi lại được thực thi trên cùng một luồng mà lệnh gọi hàm được thực hiện, vì vậy, người triển khai phải cẩn thận với việc giữ các khóa trong khi gọi hàm (và tránh chúng hoàn toàn khi có thể). Một hàm không có câu lệnh generates hoặc từ khóa oneway vẫn bị chặn; máy khách chặn cho đến khi máy chủ trả về đối tượng Return<void> .

Cuộc gọi một chiều

Khi một chức năng được đánh dấu oneway , máy khách sẽ trả về ngay lập tức và không đợi máy chủ hoàn thành việc gọi hàm của nó. Nhìn bề ngoài (và tổng hợp), điều này có nghĩa là lệnh gọi hàm mất một nửa thời gian vì nó đang thực thi một nửa mã, nhưng khi viết các triển khai nhạy cảm với hiệu suất, điều này có một số hàm ý về lập kế hoạch. Thông thường, việc sử dụng cuộc gọi một chiều sẽ khiến người gọi tiếp tục được lên lịch trong khi sử dụng cuộc gọi đồng bộ thông thường sẽ khiến bộ lập lịch chuyển ngay từ người gọi sang quy trình được gọi. Đây là một tối ưu hóa hiệu suất trong chất kết dính. Đối với các dịch vụ mà cuộc gọi một chiều phải được thực hiện trong quy trình đích với mức độ ưu tiên cao, chính sách lập lịch của dịch vụ nhận có thể được thay đổi. Trong C++, việc sử dụng phương thức setMinSchedulerPolicy của libhidltransport với các chính sách và mức độ ưu tiên của bộ lập lịch được xác định trong sched.h đảm bảo rằng tất cả lệnh gọi vào dịch vụ sẽ chạy ít nhất theo chính sách và mức độ ưu tiên lập lịch đã đặt.