Commit ba223c29da480b40b38678c66636ee9910973a47
1 parent
6d16c2f8
Add map client retry notification (Avi Kivity)
The target memory mapping API may fail if the bounce buffer resources are exhausted. Add a notification mechanism to allow clients to retry the mapping operation when resources become available again. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6395 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
42 additions
and
0 deletions
cpu-all.h
... | ... | @@ -928,6 +928,8 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, |
928 | 928 | int is_write); |
929 | 929 | void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, |
930 | 930 | int is_write, target_phys_addr_t access_len); |
931 | +void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); | |
932 | +void cpu_unregister_map_client(void *cookie); | |
931 | 933 | |
932 | 934 | uint32_t ldub_phys(target_phys_addr_t addr); |
933 | 935 | uint32_t lduw_phys(target_phys_addr_t addr); | ... | ... |
exec.c
... | ... | @@ -3053,10 +3053,49 @@ typedef struct { |
3053 | 3053 | |
3054 | 3054 | static BounceBuffer bounce; |
3055 | 3055 | |
3056 | +typedef struct MapClient { | |
3057 | + void *opaque; | |
3058 | + void (*callback)(void *opaque); | |
3059 | + LIST_ENTRY(MapClient) link; | |
3060 | +} MapClient; | |
3061 | + | |
3062 | +static LIST_HEAD(map_client_list, MapClient) map_client_list | |
3063 | + = LIST_HEAD_INITIALIZER(map_client_list); | |
3064 | + | |
3065 | +void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)) | |
3066 | +{ | |
3067 | + MapClient *client = qemu_malloc(sizeof(*client)); | |
3068 | + | |
3069 | + client->opaque = opaque; | |
3070 | + client->callback = callback; | |
3071 | + LIST_INSERT_HEAD(&map_client_list, client, link); | |
3072 | + return client; | |
3073 | +} | |
3074 | + | |
3075 | +void cpu_unregister_map_client(void *_client) | |
3076 | +{ | |
3077 | + MapClient *client = (MapClient *)_client; | |
3078 | + | |
3079 | + LIST_REMOVE(client, link); | |
3080 | +} | |
3081 | + | |
3082 | +static void cpu_notify_map_clients(void) | |
3083 | +{ | |
3084 | + MapClient *client; | |
3085 | + | |
3086 | + while (!LIST_EMPTY(&map_client_list)) { | |
3087 | + client = LIST_FIRST(&map_client_list); | |
3088 | + client->callback(client->opaque); | |
3089 | + LIST_REMOVE(client, link); | |
3090 | + } | |
3091 | +} | |
3092 | + | |
3056 | 3093 | /* Map a physical memory region into a host virtual address. |
3057 | 3094 | * May map a subset of the requested range, given by and returned in *plen. |
3058 | 3095 | * May return NULL if resources needed to perform the mapping are exhausted. |
3059 | 3096 | * Use only for reads OR writes - not for read-modify-write operations. |
3097 | + * Use cpu_register_map_client() to know when retrying the map operation is | |
3098 | + * likely to succeed. | |
3060 | 3099 | */ |
3061 | 3100 | void *cpu_physical_memory_map(target_phys_addr_t addr, |
3062 | 3101 | target_phys_addr_t *plen, |
... | ... | @@ -3146,6 +3185,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, |
3146 | 3185 | } |
3147 | 3186 | qemu_free(bounce.buffer); |
3148 | 3187 | bounce.buffer = NULL; |
3188 | + cpu_notify_map_clients(); | |
3149 | 3189 | } |
3150 | 3190 | |
3151 | 3191 | /* warning: addr must be aligned */ | ... | ... |