Commit ba223c29da480b40b38678c66636ee9910973a47

Authored by aliguori
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);
... ...
... ... @@ -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 */
... ...